第一个Google App Engine的Java程序
什么是Google App Engine?
通过使用Google App Engine,您可以在Google基础架构的基础上运行自己编写的网络应用程序,省去了租用服务器和申请域名的工作。GAE(Google App Engine)目前支持Java和Python语言。
搭建开发环境
开发普通的Java WebApplication一般使用Myeclipse,在此基础上开发GAE的程序只需要在Myeclipse上安装Google提供的插件即可。
下载App Engine Java SDK
直接解压到硬盘目录即可
安装Myeclipse插件(myeclipse版本10.0)
选择Help菜单,点击Myeclipse Configuration Center。
选择Software,点击add site,在Name中输入googleappengine3.7,在URL中输入http://dl.google.com/eclipse/plugin/3.7,点击确定。
在右侧面板中选中要添加的插件,点击右上方的绿色加号按钮
配置sdk
点击面板右上方的Applychanges,等待安装完毕重启Myeclipse。
点击windows->Preferences->Google->AppEngine,点击Add,在弹出面板中点击Browse,选择AppEngine Java SDK的解压目录,填写Display name,点击OK。
新建项目
打开Myeclipse,点击,选择New Web Application Project,弹出新建项目面板,填写projectname,package,取消选择Use Google WebToolkit。
新建的项目完整目录结构如下图所示
运行空项目
右键点击Guestbook项目,选择Run as –>Web Application,
打开浏览器,输入http://localhost:8888
点击下面的链接就可以打开我们创建的一个空项目。
使用UsersService
Google App Engine提供很多服务,其中Users Service可以允许您的应用程序添加使用Google账号登录的功能。
打开src/xidian.guestbook/GuestbookServlet.java,,编写以下代码
package xidian.guestbook;
import java.io.IOException; 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 GuestbookServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if (user != null) { resp.setContentType("text/plain"); resp.getWriter().println("Hello, " + user.getNickname()); } else { resp.sendRedirect(userService.createLoginURL(req.getRequestURI())); } } } |
再次运行,查看效果。
使用JSP
在war目录下新建jsp文件guestbook.jsp
替换为以下内容:
<%@ page contentType="text/html;charset=UTF-8" language="java"%> <%@ page import="com.google.appengine.api.users.User"%> <%@ page import="com.google.appengine.api.users.UserService"%> <%@ page import="com.google.appengine.api.users.UserServiceFactory"%>
<html> <body>
<% UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if (user != null) { %> <p> Hello,<%=user.getNickname()%>! (You can <ahref="<%=userService.createLogoutURL(request.getRequestURI())%>"> Sign out</a>.) </p> <% } else { %> <p> Hello! <a href="<%=userService.createLoginURL(request.getRequestURI())%>">Sign in</a> to include your name with greetings you post. </p> <% } %>
</body> </html>
|
为了使guestbook.jsp成为整个应用的首页,我们需要在war/WEB-INF/web.xml中
修改<welcome-file>的值为guestbook.jsp
修改后为
<welcome-file-list> <welcome-file>guestbook.jsp</welcome-file> </welcome-file-list> |
在guestbook.jsp中添加留言簿表单
在</body>标签之前,添加代码
<form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Post Greeting" /></div> </form>
</body> </html> |
添加新类SignGuestbookServlet
在src/xidian.guestbook目录下新建一个类SignGuestbookServlet.java
输入以下代码:
package xidian.guestbook;
import java.io.IOException; import java.util.logging.Logger; import javax.servlet.http.*; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory;
public class SignGuestbookServlet extends HttpServlet { private static final Logger log = Logger.getLogger(SignGuestbookServlet.class.getName());
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser();
String content = req.getParameter("content"); if (content == null) { content = "(No greeting)"; } if (user != null) { log.info("Greeting posted by user " + user.getNickname() + ": " + content); } else { log.info("Greeting posted anonymously: " + content); } resp.sendRedirect("/guestbook.jsp"); } } |
在war/WEB-INF/web.xml注册SignGuestbookServlet类,添加以下代码
<servlet> <servlet-name>sign</servlet-name> <servlet-class>xidian.guestbook.SignGuestbookServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sign</servlet-name> <url-pattern>/sign</url-pattern> </servlet-mapping> |
数据存储与JDO
在创建JDO类时可以使用Java注释说明如何在数据存储区中存储实例,以及在数据存储区中检索时如何重新创建实例。
在src/xidian.guestbook下创建一个Greeting类以表示发布到留言簿的各条消息
package xidian.guestbook;
import com.google.appengine.api.datastore.Key; import com.google.appengine.api.users.User; import java.util.Date; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable public class Greeting { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key;
@Persistent private User author;
@Persistent private String content;
@Persistent private Date date;
public Greeting(User author, String content, Date date) { this.author = author; this.content = content; this.date = date; }
public Key getKey() { return key; }
public User getAuthor() { return author; }
public String getContent() { return content; }
public Date getDate() { return date; }
public void setAuthor(User author) { this.author = author; }
public void setContent(String content) { this.content = content; }
public void setDate(Date date) { this.date = date; } } |
每个使用数据存储区的请求都会创建PersistenceManager类的实例,也可以使用PersistenceManagerFactory类的实例完成此操作。在src/xidian.guestbook中新建PMF。
package xidian.guestbook;
import javax.jdo.JDOHelper; import javax.jdo.PersistenceManagerFactory;
public final class PMF { private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");
private PMF() {}
public static PersistenceManagerFactory get() { return pmfInstance; } } |
创建和保存对象
表单处理现在可以在数据存储区中存储新的问候语。
编辑src/xidian.guestbook/SignGuestbookServlet.java
package xidian.guestbook;
import java.io.IOException; import java.util.Date; import javax.jdo.PersistenceManager; import javax.servlet.http.*; import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; import xidian.guestbook.Greeting; import xidian.guestbook.PMF;
public class SignGuestbookServlet extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser();
String content = req.getParameter("content"); Date date = new Date(); Greeting greeting = new Greeting(user, content, date);
PersistenceManager pm = PMF.get().getPersistenceManager(); try { pm.makePersistent(greeting); } finally { pm.close(); }
resp.sendRedirect("/guestbook.jsp"); } } |
使用JDOQL查询数据
修改guestbook.jsp文件
编写以下代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ 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="xidian.guestbook.Greeting" %> <%@ page import="xidian.guestbook.PMF" %>
<html> <head> </head> <body>
<% UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if (user != null) { %> <p>Hello, <%= user.getNickname() %>! (You can <a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">sign out</a>.)</p> <% } else { %> <p>Hello! <a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a> to include your name with greetings you post.</p> <% } %>
<% PersistenceManager pm = PMF.get().getPersistenceManager(); String query = "select from " + Greeting.class.getName(); List<Greeting> greetings = (List<Greeting>) pm.newQuery(query).execute(); if (greetings.isEmpty()) { %> <p>The guestbook has no messages.</p> <% } else { for (Greeting g : greetings) { if (g.getAuthor() == null) { %> <p>An anonymous person wrote:</p> <% } else { %> <p><b><%= g.getAuthor().getNickname() %></b> wrote:</p> <% } %> <blockquote><%= g.getContent() %></blockquote> <% } } pm.close(); %>
<form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Post Greeting" /></div> </form>
</body> </html> |
使用静态文件
在war/目录下创建一个名为stylesheets/的目录。在该目录中,新建一个名为main.css的文件,包含以下内容
body { font-family: Verdana, Helvetica, sans-serif; background-color: #FFFFCC; } |
编辑war/guestbook.jsp,在<head>标签之间加入引用
<head> <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" /> </head> |
上传应用
注册Google App Engine账户
在以下网址
https://accounts.google.com/ServiceLogin?service=ah&passive=true&continue=https://appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttps://appengine.google.com/<mpl=ae
使用自己的Google账号登录,然后填写相关信息进行注册
其中有一步要输入手机号码,需要在您的手机号码前加上“+86”
新建应用
登录管理平台后,可以创建新应用
在ApplicationIdentifier输入框中填写应用的唯一标识符,此处我填写的是xidianbook,那么此应用的域名就是xidianbook.appspot.com
编辑/war/WEB-INF/appengine-web.xml
在<application>标签之间输入xidianbook
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> <application>xiidanbook</application> <version>1</version> |
在myeclipse中上传
右键点击项目,选择Google->Deployto App Engine
命令行上传
拷贝项目war文件夹到App Engine Java SDK安装目录下的bin文件夹下
例如:D:\google-app-engine\appengine-java-sdk\bin
打开命令窗口进入此目录,输入 appcfg.cmd update war
过程中会提示输入google账户的邮箱和密码(输入密码时光标不会移动)
查看是否上传成功
登录GAE管理界面,点击Versions,如图所示表示成功上传
访问应用
在浏览器输入 http://xidianbook.appspot.com(需要翻墙)
快速运行Demo程序
在下载的appengine sdk中,google为我们提供了很多demo,在sdk安装路径下的demos文件夹下
例如我们运行google提供的guestbook,打开/guest/war/WEB-INF/appengine-web.xml在<application>标签之间填写应用的id;然后按照上文提到的命令行方式上传应用,拷贝整个war文件夹到/bin目录下,执行appcfg.cmdupdate war命令。