日期:2014-05-18  浏览次数:20643 次

麻雀虽小,五脏俱全:上手Google App Engine遇到的问题总结
麻雀虽小,五脏俱全系列

---

虽然经常见到云计算的相关新闻,而且在CSDN的论坛里也解答过关于Google App Engine持久化方面的问题,但并没有将这两者联系起来。我一直以为GAE是一个类似于Spring或者Hibernate一样的开源项目罢了。最近构思技术族谱这个开源项目的时候,想先找一个免费的jsp空间做做前期测试,竟然发现GAE就是Google的云计算平台,其提供的免费流量和计算能力还是相当可观的,这对我来说,无疑是天上掉下一块大馅饼。

使用Google提供的Eclipse插件,开发还是很便利的,跟写普通的JAVA web程序也没有太大的差异,不过随插件提供的本地模拟环境还是和部署后的真实环境有些差异,从开始做,到真正把一个最简单的功能(Echo)成功上线,大概花费了三天的业余时间,并遇到了几个小问题,在这里总结一下,希望对大家有用。

我的GAE版本:1.2.2

第一点,算是个注意事项吧。
GAE的插件在每次打包时,会自动清理WEB-INF/classes目录,所以struts.xml,log4j.properties等配置文件无法直接放在该目录里,可以放在src目录,或者可以再建一个独立的目录,比如cfg存放配置文件,并将该目录加为class目录即可。

第二点,JSTL标签默认无法使用(不报错,也不被解析)。
需要在jsp页面的page direction中增加isELIgnored="false",比如:
<%@ page contentType="text/html; charset=UTF-8" language="java" pageEncoding="UTF-8" isELIgnored="false"%>
官方说这可能跟他们使用的Jasper版本有关,也许在下一次升级的时候会改进。参见:http://groups.google.com/group/google-appengine-java/msg/da389df15e056697?hl=en

第三点,中文问题。
在windows上开发,默认文件编码是GBK,这时候如果JSP页面也将encoding设置为GBK的话,通常需要增加Filter来实现编码转换来消除乱码。我把整个项目全部改成UTF-8,也就是文件编码UTF-8,而且jsp中指定的charset也是UTF-8,中文问题可以自然解决(不用增加额外的filter)。

第四点,整合了Struts2,但默认情况下,由于ONGL权限导致部署后的应用访问失败。
这个问题在本地测试不会出现,但部署上去就会抛出如下异常:
错误信息:
08-31 08:37AM 19.209 /xxxxxxx.action?fromUrlEncode=%E7%BC%96%E7%A0%81&fromUrlNonEncode=%E6%9C%AA%E7%BC%96%E7%A0%81 404 86ms 158cpu_ms 0kb Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729),gzip(gfe)
See details
117.79.68.140 - - [31/Aug/2009:08:37:19 -0700] "POST /xxxxxxxx.action?fromUrlEncode=%E7%BC%96%E7%A0%81&fromUrlNonEncode=%E6%9C%AA%E7%BC%96%E7%A0%81 HTTP/1.1" 404 0 "http://jszupu.appspot.com/xxxxxxx.jsp" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729),gzip(gfe)" "jszupu.appspot.com"

官方说是因为实际运行环境的安全设置和插件带的模拟环境不太一样,并给出了一个解决方案,需要增加一个Listener,listener内容如下:
Java code
   1. public class OnglPermissionListener implements ServletContextListener{  
   2.     public OnglPermissionListener()  {   
   3.     }   
   4.   
   5.     public void contextInitialized(ServletContextEvent sce)  {   
   6.         OgnlRuntime.setSecurityManager(null);   
   7.     }  
   8.   
   9.     public void contextDestroyed(ServletContextEvent arg0) {          
  10.     }     
  11.   
  12. }  


官方关于这个问题的讨论请参见:http://groups.google.com/group/google-appengine-java/browse_thread/thread/19018b0317f27817

第五点,如果使用了标签文件,则本地可测试通过,但部署时出错。
标签文件是指在WEB-INF/tags目录下编写的JSTL自定义标签,不是指的用TLD文件定义的标准JSP自定义标签。
如果用到了这种标签文件,那么在部署的时候会出错:
2009-9-5 19:35:04 org.apache.jasper.compiler.Compiler generateClass
严重: Javac exception
Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK

关于这个问题,google官方也只给出了一个很差的解决方案,就是把jre/lib下的tools.jar拷贝到AppEngine的安装目录/lib/share,相关问题描述和讨论过程参见:
http://groups.google.com/group/google-appengine-java/browse_thread/thread/225d7a555cbc0100/1a9cd7c6f39e663a?lnk=raot
http://groups.google.com/group/google-appengine-java/browse_thread/thread/175e70cc0c93ded9

第六点,标签文件中的中文乱码。
JSP页面用UTF-8,中文没有任何问题,但标签文件用UTF-8就不行,这个我没有找到解决方案,网上讨论的资料也很少,不知道是不是跟我机器环境有关,最后干脆在标签文件中不写中文,全用Resource Bundle来做。

第七点,jstl标签的应用方式问题。
在jsp中,jstl标签可以用如下URL引入:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
而在标签文件中,只能用
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
才有效,参见:
http://groups.google.com/group/google-appengine-java/browse_thread/thread/affd7e7a83f614e1