在Google App Engine中应用Struts2框架

在Google App Engine中使用Struts2框架
"GAE"(Google App Engine)在早些时候发布了Java语言的支持,对广大的Java开发者来说,可以使用自己熟悉的语法来进行开发

,是很舒服的一件事情。Java世界中有大量已有的工具和框架,有一些是我们日常工作中就已经熟练使用的、而且广为流行的成熟

的,如果能够直接在GAE中使用,将大大提高我们的开发效率。

  这几天利用Struts2,在GAE的Java版本支持环境中,写了个简单博客,现在将GAE + Struts2的组合经验,记录下来。

  背景介绍

  Python是一门有趣的语言,是作者第二个接触的动态脚本语言。第一个是大学时期做学生网站时期接触到Perl,后来工作后利

用Perl改写了公司的应用程序启动框架;几年后,由于Perl的语法实在是太过于羞涩难懂,便使用Python对启动框架进行了一次升

级。Python是面向对象的,同时也兼备了函数式编程的支持,另外,Python的语法强制缩进,非常容易读懂,因此Python版本的启

动框架对公司的Java开发者来说,也不难维护。

  当然,这些都是题外话,GAE最先提供的是Python语言的支持,但是对我们Java开发者来说,要使用Python来进行大的应用开发

,还比较痛苦的一件事情。这时候GAE推出Java语言的支持,既是所有Java开发人员的福音,也是理所当然的一件事情,Google不可

能放弃目前企业应用开发领域里面最大的一股力量。

  Struts2是目前应用最广泛的WEB开发框架,也是大部分的Java开发者最熟悉的开发框架,我们的GAE应用程序中,使用成熟的

Struts2可以减少很多额外的开发工作。

  所需的Struts的库文件

  目前Struts2的稳定版本是2.1.6,将下面的来自Struts-2.1.6的发行包的几个包,引入你的GAE项目工程中:

  commons-fileupload-1.2.1.jareqpg 2009-9-8 12:05
  commons-io-1.3.2.jar

  commons-logging-1.0.4.jar

  commons-logging-api-1.1.jar

  freemarker-2.3.13.jar

  ognl-2.6.11.jar

  struts2-core-2.1.6.jar

  xwork-2.1.2.jar

  如果你使用IDEA来创建项目,只要选择Struts的2.1.6版本的支持,IDEA会自动帮你引入所需要的库文件。

  为App Engine定制你的Struts

  GAE里面的Servlet环境有一定的限制,不能使用线程(Thread),不能使用文件,还有别的一些要注意的地方。

  首先,要加一个ServletContextListener的实现,在context初始化的时候,调用OgnlRuntime.setSecurityManager(null),让

Struts可以在GAE环境里面正常跑起来:

package your.servlet.pkg; 
 
import ognl.OgnlRuntime; 
 
import javax.servlet.ServletContextListener; 
import javax.servlet.ServletContextEvent; 
 
public class StrutsAppEngineAdapter implements ServletContextListener { 
  public void contextInitialized(ServletContextEvent servletContextEvent) { 
    OgnlRuntime.setSecurityManager(null); 
  } 
 
  public void contextDestroyed(ServletContextEvent servletContextEvent) { 
  } 
} 

  在web.xml中配置这个ServletContextListener的实例:

<web-app> 
 <listener> 
  <listener-class>your.servlet.pkg.StrutsAppEngineAdapter</listener-class> 
 </listener> 
</web-app> eqpg 2009-9-8 12:06
  做完上面的工作之后,就可以在你的GAE里面使用Struts的功能了!

  定制GAE的常用对象的Converter

  Struts提供了Converter的机制,让你常用的业务对象可以直接在页面中显示,或者接受类型为业务对象的请求数据。GAE里面

常用的一些对象,定义了对应的Converter之后,可以是业务代码更加简洁。下面介绍两个常用对象的Converter的代码:

  TextConverter, 是针对com.google.appengine.api.datastore.Text对象的转换器,Text是GAE的存储中,大文本内容的保存对

象,在业务中很常用。先来看看TextConverter大的代码:

package your.servlet.pkg; 
 
import com.google.appengine.api.datastore.Text; 
import ognl.DefaultTypeConverter; 
 
import java.util.Map; 
 
public class TextConverter extends DefaultTypeConverter { 
  @Override 
  public Object convertValue(Map map, Object o, Class toType) { 
    if (toType == Text.class) { 
      String value = ((String[]) o)[0]; 
      return new Text(value); 
    } else if (toType == String.class) { 
      Text text = (Text) o; 
      return text.getValue(); 
    } 
 
    return null; 
  } 
} 

  TextConverter的作用主要是用于在WEB页面中,直接显示存储对象中的大文本内容。

  另外一个是KeyConverter,是对com.google.appengine.api.datastore.Key对象的转换器,Key是 GAE中三种主键(Long,

String,Key)的一种,在接收请求数据以及页面显示的时候,会经常用到。直接看代码:eqpg 2009-9-8 12:06
package your.servlet.pkg; 
 
import com.google.appengine.api.datastore.Key; 
import com.google.appengine.api.datastore.KeyFactory; 
import ognl.DefaultTypeConverter; 
 
import java.util.Map; 
 
public class KeyConverter extends DefaultTypeConverter { 
  @Override 
  public Object convertValue(Map map, Object o, Class toType) { 
    if (toType == Key.class) { 
      String s = ((String[]) o)[0]; 
      return KeyFactory.stringToKey(s); 
    } else if (toType == String.class) { 
      Key k = (Key) o; 
      return KeyFactory.keyToString(k); 
    } 
 
    return null; 
  } 
} 

  在源代码的根目录,创建xwork-conversion.properties文件,内容如下:

com.google.appengine.api.datastore.Text=your.servlet.pkg.TextConverter 
com.google.appengine.api.datastore.Key=your.servlet.pkg.KeyConverter 

  上面的工作都完成以后,就可以在你的Action里面直接使用Key类型的类变量,无需手工去做String和Key之间的转换!

  Convention Plugin不能使用

  Struts2里面,最常用的Plugin应该是Convertion了,"零配置"即减少了写配置文件的麻烦,代码的组织结构看起来也清晰很多



  但是在GAE里面,无法读取文件系统,目前的Convertion版本还无法正常工作,非常可惜。不过建议你的GAE应用中,Action和

JSP文件,还是按照Convertion Plugin的组织方式来存放,一方面有利于后面的升级和迁移工作,另一方面也让你的应用的文件看

起来更清晰。