在确定了IDE和Server之后,就要选择一个web框架了。我选择的是struts2,因为它的使用率很高,网上也很多资源,遇到问题好查。
struts2网上的最新版是2.2.1。
创建项目
打开MyEclipse,新建一个Google Web Application:
创建完成后的文件结构如下:
因为我们不用servlet,所以为了看上去清静一些,让我们删除GAE插件生成的Struts2TestServlet.java,index.html,并删除web.xml中关于servlet的东西。
添加struts的库
把下载下来的struts 2.2.1的如下几个jar复制到war\WEB-INF\lib下:
- commons-fileupload-1.2.1.jar
- commons-io-1.3.2.jar
- commons-logging-1.0.4.jar
- freemarker-2.3.16.jar
- ognl-3.0.jar
- struts2-core-2.2.1.jar
- xwork-2.2.1.jar
- javassist-3.7.ga.jar
其中,前面7个jar在struts 2.2.1的lib下面可以找到,最后一个javassist-3.7.ga.jar则需要在apps\struts2-blank-2.2.1\WEB-INF\lib下面找。
右键点击Struts2Test项目的属性,选择“Java 构建路径”,并选择“库(L)”,如下图:
点击“添加jar…”,在弹出的对话框里选择lib下的那几个struts2的jar,如下图:
完成之后,项目结构中会多出一个“引用的库”,如下图:
配置web.xml
打开war\WEB-INF\web.xml,把它修改为:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
配置完之后,在MyEclipse中运行Struts2Test项目,可以看到Google app engine的web server正常的启动起来了。
添加Action
添加一个类,名为LoginAction,如下图:
修改LoginAction的内容如下:
package kong.test;
import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
public class LoginAction extends ActionSupport{
private String userName;
private String password;
public void setUserName(String name){
userName = name;
}
public void setPassword(String pwd){
password = pwd;
}
public String execute(){
if(userName.equals("gae") && password.equals("struts2")){
addActionMessage("Welcome," + userName);
return SUCCESS;
}
addActionError("Username and Password Combination doesnot match.");
return INPUT;
}
}
在src目录下添加structs.xml,内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="struts2" namespace="/member"
extends="struts-default">
<action name="login">
<result>/login.jsp</result>
</action>
<action name="home" class="kong.test.LoginAction">
<result name="input">/login.jsp</result>
<result>/home.jsp</result>
</action>
</package>
</struts>
在war下添加login.jsp和home.jsp,内容分别如下:
login.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>登录</title>
</head>
<body>
<s:actionerror/>
<s:form action="home" method="post">
<s:textfield name="userName" label="用户名"></s:textfield>
<s:textfield name="password" label="密码"></s:textfield>
<s:submit name="login" value="登录"></s:submit>
</s:form>
</body>
</html>
home.jsp:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>首页</title>
</head>
<body>
<s:actionmessage />
</body>
</html>
测试一下
启动Google app engine的server,看到启动成功的消息之后,打开浏览器输入http://localhost:8888/member/login,结果出错了:
HTTP ERROR 404
Problem accessing /member/login. Reason:
result 'null' not found
Google之后知道,为了解决这个问题,要弄一个listener。添加类StrutsAppEngineAdapter,内容如下:
package kong.test;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import ognl.OgnlRuntime;
public class StrutsAppEngineAdapter implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
OgnlRuntime.setSecurityManager(null);
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
修改web.xml,把这个listener加进来:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>kong.test.StrutsAppEngineAdapter</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
重启gae的web server,再运行一下,又出了另一个错误:
HTTP ERROR 500
Problem accessing /member/login. Reason:
java.lang.NoClassDefFoundError: javax.swing.tree.TreeNode is a restricted class. Please see the Google App Engine developer's guide for more details.
Caused by:
javax.servlet.ServletException: java.lang.NoClassDefFoundError: javax.swing.tree.TreeNode is a restricted class. Please see the Google App Engine developer's guide for more details.
at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:825)
at org.apache.jasper.runtime.PageContextImpl.access$1100(PageContextImpl.java:64)
...
继续Google,为了解决这个问题,我们需要新建一个包freemarker.core,并加一个TextBlock类进来才行,该类的代码比较大,所以就不贴了,可以从这里下载。
加了TextBlock之后,重新启动gae的server,然后刷新http://localhost:8888/member/login,终于不出错了!输入用户名gae,密码struts2,成功跳到了home。
最后,把它发布到Google app engine上去,也是可以成功运行的:
参考文章:http://whyjava.wordpress.com/2009/08/30/creating-struts2-application-on-google-app-engine-gae/