GAE-简单的留言板(Simple Guestbook)

这个例子其实就是Google官方给出来的例子~你可以在文档中看到,我在原例子的基础上添加了修改与删除功能~(没判断权限~谁都可以删除~要判断也很简单…判断一下登陆的email)

我就不说那么详细了·官方例子说的已经很清楚了,需要源码在这里下载:http://115.com/file/bhqlcqtq

这个例子显示效果在此:http://1.latest.fatkuns.appspot.com/

这个例子涉及了

  1. 如何使用用户服务(也就是使用google账号登陆~我有点担心的是别人伪造一个假的登录页面怎么办?放心,我做的那个是真的…- -!)
  2. 如何存储数据(使用JDO)
  3. JSP
  4. Servlet

好~开始了~那些准备工作就不说了,创建项目,包名这些~

一、要保存留言,我们需要创建一个这样的文件~Greeting.java

package com.fatkun.guestbook;
 
import java.util.Date;
 
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
 
import com.google.appengine.api.users.User;
 
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Greeting {
	//主键的设置,自增的方式
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Long id;
	//其他的值设置一个@Persistent在前面就会保存到数据库里了
	@Persistent
	private User author;
	@Persistent
	private String content;
	@Persistent
	private Date date;
 
	//下面是一些Getter,Setter方法,对于JDO是不需要的,只是为了方便你写程序
	public Greeting(User author, String content, Date date) {
		super();
		this.author = author;
		this.content = content;
		this.date = date;
	}
 
	public Long getId() {
		return id;
	}
 
	public void setId(Long id) {
		this.id = id;
	}
 
	public User getAuthor() {
		return author;
	}
 
	public void setAuthor(User author) {
		this.author = author;
	}
 
	public String getContent() {
		return content;
	}
 
	public void setContent(String content) {
		this.content = content;
	}
 
	public Date getDate() {
		return date;
	}
 
	public void setDate(Date date) {
		this.date = date;
	}
 
}

二、我们还要创建PMF.java用来取得PersistenceManager。官方说取这个东西要花费很多资源,所以只获得一个就好,单例模式~

package com.fatkun.guestbook;
 
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
 
/**
 * 用来取得PersistenceManager
 * @author Administrator
 *
 */
public final class PMF {
	private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");
 
	private PMF() {
	}
 
	public static PersistenceManagerFactory get() {
		return pmfInstance;
	}
}

三、我们在war目录下新建一个guestbook.jsp用来显示所有留言

<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.List"%>
<%@ page import="javax.jdo.PersistenceManager"%>
<%@ page import="com.google.appengine.api.users.User"%>
<%@ page import="com.google.appengine.api.users.UserService"%>
<%@ page import="com.google.appengine.api.users.UserServiceFactory"%>
<%@ page import="com.fatkun.guestbook.Greeting"%>
<%@ page import="com.fatkun.guestbook.PMF"%>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Google App Engine留言板 - fatkun.com</title>
</head>
<body>
<%
	UserService userService = UserServiceFactory.getUserService();
	User user = userService.getCurrentUser();
	if (user != null) {
%>
<p>你好, <%=user.getNickname()%>! (<a href="<%=userService.createLogoutURL(request.getRequestURI())%>">退出</a>.)</p>
<%
	} else {
%>
<p>你好! 你可以使用google账号<a href="<%=userService.createLoginURL(request.getRequestURI())%>">登陆</a></p>
<%
	}
%>
 
<%
	PersistenceManager pm = PMF.get().getPersistenceManager();
	//String query = "select from " + Greeting.class.getName()+" order by id desc";
	//也可以写成下面的形式
	String query = "select from com.fatkun.guestbook.Greeting order by id desc";
	List<Greeting> greetings = (List<Greeting>) pm.newQuery(query).execute();
	if (greetings.isEmpty()) {
%>
<p>还没有留言。</p>
<%
	} else {
		for (Greeting g : greetings) {
			if (g.getAuthor() == null) {
				out.print("<p>一位匿名人士说:</p>");
			} else {
				out.print("<p><b>"+g.getAuthor().getNickname()+"</b> 说:</p>");
			}
%>
<a href="del?id=<%=g.getId()%>">删除</a> - <a href="guestbook-modify.jsp?id=<%=g.getId()%>">修改</a>
<blockquote><%=g.getContent()%></blockquote>
<%
	}
	}
	pm.close();
%>
 
<form action="/add" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="我要留言" /></div>
</form>
 
</body>
</html>

这里注意要引入自己使用的包~~GQL是针对对象来写查询语句的~~有点儿像Hibernate的HQL~

四、没有内容怎么显示呢~我们加一个添加到数据库的GuestbookAddServlet.java

package com.fatkun.guestbook;
 
import java.io.IOException;
import java.util.Date;
 
import javax.jdo.PersistenceManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
 
@SuppressWarnings("serial")
public class GuestbookAddServlet extends HttpServlet {
 
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//取得用户Service,这里是Google的用户管理
		UserService userService = UserServiceFactory.getUserService();
		//取得当前登录的用户,当不存在的时候为null
		User user = userService.getCurrentUser();
 
		String content = req.getParameter("content");
		Date date = new Date();
		//创建一个Greeting对象
		Greeting greeting = new Greeting(user, content, date);
 
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			//持久化~也就是把greeting添加进数据库
			pm.makePersistent(greeting);
		} finally {
			pm.close();
		}
		resp.sendRedirect("guestbook.jsp");
	}
 
}

写完了上面这个文件,注意还得在web.xml加入下面的,要告诉服务器说,我在这里啊,你可以通过这个链接找我~~

	<servlet>
		<servlet-name>add</servlet-name>
		<servlet-class>com.fatkun.guestbook.GuestbookAddServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>add</servlet-name>
		<url-pattern>/add</url-pattern>
	</servlet-mapping>

这时,你应该就可以留言啦~~运行一下试试~~可以先在本地测试,再上传到GAE服务器上。

伍、我最后给出修改和删除的部分代码~其实就主要是数据库的问题~~

GuestbookModifyServlet.java

	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Long id = Long.parseLong(req.getParameter("id"));
		String content = req.getParameter("content");
 
		//先获取PersistenceManager
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			//根据ID从数据库得到一条记录
			Greeting greeting = pm.getObjectById(Greeting.class, id);
			//修改记录
			greeting.setContent(content);
		} finally {
			//当关闭pm的时候,会自动把已经修改的记录更新到数据库
			pm.close();
		}
		resp.sendRedirect("guestbook.jsp");
	}

GuestbookDeleteServlet.java

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		Long id = Long.parseLong(req.getParameter("id"));
 
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			//取得这条记录
			Greeting greeting = pm.getObjectById(Greeting.class, id);
			//删除
			pm.deletePersistent(greeting);
		} finally {
			//关闭
			pm.close();
		}
		resp.sendRedirect("guestbook.jsp");
	}

好,一个简单的留言板就这样诞生了~~如果想弄得更加漂亮,就自己弄吧~~^_^
我做的例子:http://1.latest.fatkuns.appspot.com/




fatkun

163条评论

Merry Christmas ~ O(∩_∩)O ~

      *       ,
            _/^\_
           
   *         /.-.\     *
       *    `/&\`          *
           ,@.*;@,
           /_o.I %_\  *
    *      (`’–:o(_@;
          /`;–.,__ `’)       *
         ;@`o % O,*`’`&\
      *  (`’–)_@ ;o %’()\   *
         /`;–._`”–._O’@;
        /&*,()~o`;-.,_ `””`)
   *     /`,@ ;+& () o*`;-’;\
        (`””–.,_0o*`;-’ &()\
        /-.,_  “”–….-’`) *
     *  /@%;o`:;’–,.__  __.’\
       ;*,&(); @ % &^;~`”`o;@();     *
       /()dev & ().oFriendsO\
       `”=”==””==,,,.,=”==”===”`
      __.—-.(\-”#####—…___…—–._
     ‘`     \)_`”””””`
            .–’ ‘)
           o( )_-\
            `”””` `

我正在学习GAE,能不能把你这个留言板的源代码发给我学习一下,我的邮箱是honghere@163.com

@hong,已经发到了你的邮箱。 我把war\WEB-INF\lib删了,你用IDE建一个GAE空白项目,把生成的lib目录下的所有jar复制过来就可以了。

能否将源代码发给我一份,我实现修改时出现了问题,想参考一下

你好,能否将源码发给我一份??
——
我知道你邮箱了,帮你去掉先,晚上再给你发。。

能不能把源代码发给我一份,我现在在学这个,遇到了一些问题

你好,能否也给我一份源码?
我按照官网上配的jdoconfig.xml
但是老是报错
谢谢了

收到源码了
但是IDEA9老是报错
警告: /
javax.jdo.JDOUserException: Persistent class “Class guestbook.Greeting does not seem to have been enhanced. You may want to rerun the enhancer and check for errors in the output.” has no table in the database, but the operation requires it. Please check the specification of the MetaData for this class.
不知道咋解决,明天再弄到eclipse上试试

[url=http://www.qgxqm.com/QQ-qinglvqianming/]qq情侣个性签名一对[/url]

[url=http://www.qgxqm.com/QQ-gaoxiaoqianming/]qq搞笑个性签名[/url]

我发了错误提示信息而已。你能把你的代码发给我参考下不。我在增强数据类的时候一直报错。

您好,您说的
add
com.whl.guestbook.GuestbookAddServlet

add
/add

是加在war/web-inf下的web.xml里面吗?我加进去了,可是然后运行Web Application会有警告如下:
2011-1-18 14:07:32 com.google.apphosting.utils.jetty.JettyLogger info
信息: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
2011-1-18 14:07:32 com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
信息: Successfully processed G:\workspace\Guestbook\war\WEB-INF/appengine-web.xml
2011-1-18 14:07:32 com.google.apphosting.utils.jetty.JettyLogger warn
警告: FATAL@null line:20 col:6 : org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.
2011-1-18 14:07:32 com.google.apphosting.utils.config.AbstractConfigXmlReader getTopLevelNode
严重: Received SAXException parsing the input stream for G:\workspace\Guestbook\war\WEB-INF/web.xml
org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.
….省略
… 12 more

为什么啊?急求?谢谢

上面那个我说的加入的xml中的是您说的

add
com.fatkun.guestbook.GuestbookAddServlet

add
/add

好像格式有问题,就是servlet中的add的部分,那个添加到xml中后有警告啊。。。

可是我在删除留言的时候有这个错误:
HTTP ERROR 404
Problem accessing /del. Reason:

NOT_FOUND

当时的url为:http://localhost:8888/del?id=4
这是为什么啊?谢谢fatkun了~~~

我也有一樣的問提 就是新增及修改那邊有錯誤,可否給我代碼,
另外用帳號來判斷權限的部分如何做? 可否講解一下

代码晚上发给你。。但愿我还记得= =!不记得再提醒我一次。。

与此同时eclipse控制台提示的警告是:
2011-1-18 23:24:42 com.google.appengine.tools.development.LocalResourceFileServlet doGet
WARNING: No file found for: /del

为什么启动Web Application时eclipse会给出这样的警告呢:而且
严重: javax.servlet.ServletContext log: unavailable
javax.servlet.UnavailableException: Servlet class com.fatkun.guestbook.GuestbookModifyServlet is not a javax.servlet.Servlet
at org.mortbay.jetty.servlet.ServletHolder.checkServletType(ServletHolder.java:362)
at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:243)

您太强了!我都弄了好几天了,效果依然没出来,崩溃的边缘!请您把源码借我欣赏一下吧!如果您愿意的话,把QQ也告诉我吧!非常非常感谢!

兄弟,发一份哦,351558205qq.com

正在研究GAE,这个好东东!感谢分享!
能发我一份代码吗?多谢啊!!

发表评论

电子邮件地址不会被公开。