在gae平台上开发jsp网站

准备工作:

下载apache-ant, googleappengine-sdk, jdk等工具



写一个简单的环境设置脚本

setenv.bat

@echo off
cd %~dp0 && echo CWD=%cd%

set GAE_HOME=""
for /d %%i in (appengine*) do (
	set GAE_HOME=%CD%\%%i
)
echo GAE_HOME=%GAE_HOME%

set JAVA_HOME=""
for /d %%i in (jdk*) do (
	set JAVA_HOME=%CD%\%%i
)
echo JAVA_HOME=%JAVA_HOME%

set ANT_HOME=""
for /d %%i in (apache-ant-*) do (
	set ANT_HOME=%CD%\%%i
)
echo ANT_HOME=%ANT_HOME%

SET PATH=%JAVA_HOME%\BIN;%GAE_HOME%\BIN;%ANT_HOME%\BIN;%PATH%;

@echo on

%comspec%


关于jsp编译失败的问题,可以参考这个,

http://stackoverflow.com/questions/5622726/unable-to-update-app-failed-to-compile-jsp-files

所以要修改上面的脚本,保证JAVA_HOME的bin路径是在本地PATH路径之前,因为path里面很可能包含了jre的java.exe的路径.


1, 复制库文件到APPID目录下的src子目录

cp -rf $GAE_SDK_HOME/{shared, user} src

按照sdk目录的lib字母下的readme文件的说明,shared和user是和用户app的执行与编译相关的。


2, 扫描所有的jar包

在你的app项目的src目录下执行

for /r %i in (*.jar) do @echo %i 

得到:

D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\jdo2-api-2.3-eb.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\appengine-local-runtime-shared.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\el-api.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp-api.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\servlet-api.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-ant-1.7.1.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-ant-launcher-1.7.1.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-jasper-6.0.29.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-jasper-el-6.0.29.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-tomcat-juli-6.0.29.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\appengine-api-1.0-sdk-1.7.7.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\appengine-api-labs-1.7.7.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\appengine-jsr107cache-1.7.7.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\jsr107cache-1.1.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\datanucleus-appengine-1.0.10.final.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\datanucleus-core-1.1.5.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\datanucleus-jpa-1.1.5.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\geronimo-jpa_3.0_spec-1.1.1.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\geronimo-jta_1.1_spec-1.1.1.jar 
D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\jdo2-api-2.3-eb.jar 


编写2个简单的java类


Res.java

package bagebit;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.http.*;

public class Res extends HttpServlet {
    private static final Logger log = Logger.getLogger(Res.class.getName());

    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
		throws IOException {
			log.info("Res::doGet called at: " + (new java.util.Date()).toString());
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().println("<b>Hello, " + req.getRequestURI() +"</b>");
    }
}


User.java
package bagebit;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.http.*;

public class User extends HttpServlet {

    private static final Logger log = Logger.getLogger(User.class.getName());

    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
		throws IOException {
			log.info("User::doGet called at: " + (new java.util.Date()).toString());
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().println("<b>Hello, " + req.getRequestURI() +"</b>");
    }
}



在app目录下,执行 batbuild.bat脚本编译java文件:

set APPID=bagebit
set CLASSPATH="D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\jdo2-api-2.3-eb.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\appengine-local-runtime-shared.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\el-api.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp-api.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\servlet-api.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-ant-1.7.1.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-ant-launcher-1.7.1.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-jasper-6.0.29.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-jasper-el-6.0.29.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\shared\jsp\repackaged-appengine-tomcat-juli-6.0.29.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\appengine-api-1.0-sdk-1.7.7.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\appengine-api-labs-1.7.7.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\appengine-jsr107cache-1.7.7.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\jsr107cache-1.1.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\datanucleus-appengine-1.0.10.final.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\datanucleus-core-1.1.5.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\datanucleus-jpa-1.1.5.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\geronimo-jpa_3.0_spec-1.1.1.jar;D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit\src\user\orm\geronimo-jta_1.1_spec-1.1.1.jar"
javac -encoding UTF-8 src\%APPID%\*.java -d war\WEB-INF\classes

这个时候可以在$APPID\war\WEB-INF\classes\$APP_PACKAGE_NAME里面就可以看到生成的class文件了。

User.java -> User.class
Res.java -> Res.class



配置servlet映射:

打开$APPID/war/WEB-INF/web.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <servlet>
        <servlet-name>user</servlet-name>
        <servlet-class>bagebit.User</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>user</servlet-name>
        <url-pattern>/user</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>res</servlet-name>
        <servlet-class>bagebit.Res</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>res</servlet-name>
        <url-pattern>/res</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

运行测试用的jetty服务器

D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit>dev_appserver -p 8888 war
2013-4-22 17:30:41 com.google.apphosting.utils.config.AppEngineWebXmlReader read
AppEngineWebXml
信息: Successfully processed D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebi
t\war\WEB-INF/appengine-web.xml
2013-04-22 17:30:41.379:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2013-4-22 17:30:41 com.google.apphosting.utils.config.AbstractConfigXmlReader re
adConfigXml
信息: Successfully processed D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebi
t\war\WEB-INF/web.xml
2013-4-22 17:30:41 com.google.appengine.tools.development.SystemPropertiesManage
r setSystemProperties
信息: Overwriting system property key 'java.util.logging.config.file', value 'D:
\webdev\gae\appengine-java-sdk-1.7.7\config\sdk\logging.properties' with value '
WEB-INF/logging.properties' from 'D:\webdev\gae\appengine-java-sdk-1.7.7\demos\b
agebit\war\WEB-INF\appengine-web.xml'
2013-04-22 17:30:41.695:INFO::jetty-6.1.x
2013-04-22 17:30:42.671:INFO::Started [email protected]:8888
2013-4-22 9:30:42 com.google.appengine.tools.development.AbstractServer startup
信息: Server default is running at http://localhost:8888/
2013-4-22 9:30:42 com.google.appengine.tools.development.AbstractServer startup
信息: The admin console is running at http://localhost:8888/_ah/admin
2013-4-22 9:30:42 com.google.appengine.tools.development.DevAppServerImpl start
信息: Dev App Server is now running


在浏览器里面测试

HTTP ERROR 500

Problem accessing /. Reason:

    Unable to compile class for JSP: 

An error occurred at line: 7 in the generated java file
Only a type can be imported. com.google.appengine.api.users.User resolves to a package

An error occurred at line: 8 in the generated java file
Only a type can be imported. com.google.appengine.api.users.UserService resolves to a package

An error occurred at line: 9 in the generated java file
Only a type can be imported. com.google.appengine.api.users.UserServiceFactory resolves to a package

出错了,看来的首页index.jsp编译失败了。

原因是没有复制相应的jsp支持库到WEB-INF的lib目录下。


从刚才复制过去的src目录下的user子目录复制,或者从sdk的lib目录的user子目录复制,保持文件夹结构。

D:\webdev\gae\appengine-java-sdk-1.7.7\demos\bagebit>xcopy /Y /e /s src\user war
\WEB-INF\lib
src\user\appengine-api-1.0-sdk-1.7.7.jar
src\user\appengine-api-labs-1.7.7.jar
src\user\appengine-jsr107cache-1.7.7.jar
src\user\jsr107cache-1.1.jar
src\user\orm\datanucleus-appengine-1.0.10.final.jar
src\user\orm\datanucleus-core-1.1.5.jar
src\user\orm\datanucleus-jpa-1.1.5.jar
src\user\orm\geronimo-jpa_3.0_spec-1.1.1.jar
src\user\orm\geronimo-jta_1.1_spec-1.1.1.jar
src\user\orm\jdo2-api-2.3-eb.jar
复制了 10 个文件

shared目录就不必了,看lib的readme文档。

具体复制那些jar包是必要的可以参考guestbook例子里面的WEB-INF/lib下面的样子。


注意:在update到服务器的时候,请记住把你的项目里面gae自带的的jar包删掉。

比如,刚才user目录下复制过来的那些jar包都不要上传了,自己额外添加的3rd的jar包可以一起上传上去。因为sdk自带的这些jar包,服务器已经为你准备好这些了。

否则很多巨大的jar包上传可能会失败,出现什么--enable-jar-splitting的提示。


注意:gae自带的demos里面的那些例子,也就guestbook添加了辅助的jar包,所以用dev_appserver -p 8888 war可以测试,其他的例子好像都不能运行,起码我试验的几个是不行的。


OK, 页面出来了。

在gae平台上开发jsp网站_第1张图片


改个简单的jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ 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.google.appengine.api.datastore.DatastoreServiceFactory" %>
<%@ page import="com.google.appengine.api.datastore.DatastoreService" %>
<%@ page import="com.google.appengine.api.datastore.Query" %>
<%@ page import="com.google.appengine.api.datastore.Entity" %>
<%@ page import="com.google.appengine.api.datastore.FetchOptions" %>
<%@ page import="com.google.appengine.api.datastore.Key" %>
<%@ page import="com.google.appengine.api.datastore.KeyFactory" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<html>
  <head>
    <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
  </head>
  <body>
    <form action="/res?write" method="Post">
      <div><input type="text" name="guestbookName" value="${fn:escapeXml(guestbookName)}"/></div>
      <div><input type="submit" value="Commit" /></div>
    </form>
  </body>
</html>


不需要重启服务器,jsp文件可以立即生效的。

这是jetty的可配置选项。

在gae平台上开发jsp网站_第2张图片


提交一下到servlet,让java来处理吧。

报错了,HTTP405, 

原因是,index.jsp是用post方式请求的,但是res.java没有实现doPost()方法

在gae平台上开发jsp网站_第3张图片


更有用的来了,开始吧。。。

后端存储,即“数据库操作”, 请先复习google的数据存储策略,google的大数据本身很厉害,有google做我们的后端,可以放心了。

https://developers.google.com/appengine/docs/java/gettingstarted/usingdatastore


新建一个Broker.java

package bagebit;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.http.*;

public class Broker extends HttpServlet {

    private static final Logger log = Logger.getLogger(Broker.class.getName());

    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
		throws IOException {
			log.info("Broker::doGet called at: " + (new java.util.Date()).toString());
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().println("<b>Hello, " + req.getRequestURI() +"</b>");
    }
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp) 
		throws IOException {
			log.info("Res::doPost called at: " + (new java.util.Date()).toString());
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().println("<b>Hello, " + req.getRequestURI() +"</b>");
    }
}

修改web.xml的映射

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <servlet>
        <servlet-name>SERVLET_KEY_do</servlet-name>
        <servlet-class>bagebit.Broker</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SERVLET_KEY_do</servlet-name>
        <url-pattern>/do</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>




你可能感兴趣的:(java,jsp,Engine,Google,APP,GAE)