原文:Mkyong
GAE + JSF:无法实例化 expression factory“com . sun . El . expression factory impl”
问题
JSF 应用程序能够部署在本地 GAE 环境中,开发环境如下:
- JSF 2.1.7
- 谷歌应用引擎 SDK 1.6.3
但是在 GAE 生产环境中部署时出现错误消息。下面是 GAE 记录的错误消息。
com.sun.faces.config.ConfigureListener installExpressionFactory: Unable to instantiate ExpressionFactory 'com.sun.el.ExpressionFactoryImpl'
E 2012-04-24 03:37:37.989
com.sun.faces.config.ConfigureListener contextInitialized: Critical error during deployment:
com.sun.faces.config.ConfigurationException:
It appears the JSP version of the container is older than 2.1 and unable to locate the EL RI expression factory,
com.sun.el.ExpressionFactoryImpl. If not using JSP or the EL RI, make sure the context initialization parameter,
com.sun.faces.expressionFactory, is properly set.
at com.sun.faces.config.ConfigureListener.registerELResolverAndListenerWithJsp(ConfigureListener.java:662)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:243)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:202)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:171)
at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:123)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:446)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:449)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:455)
at com.google.tracing.TraceContext.runInContext(TraceContext.java:695)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:333)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:325)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:453)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
at java.lang.Thread.run(Thread.java:679)
解决办法
GAE + JSF 需要 el-ri.jar 。要解决它,找到并获取 el-ri.jar ,并将其复制到您的“ /war/lib ”文件夹中。
Where to get el-ri.jar?
The faster way is get the el-ri.jar from Maven repository. ## 参考
GAE + JSF:无法恢复 View /hello.xhtml
问题
部署在 GAE 生产环境中,当从一个页面/视图导航到另一个页面/视图时,GAE 显示错误消息“视图 xxx 无法恢复”?
- JSF 2.1.7
- 谷歌应用引擎 SDK 1.6.3

在 GAE 当地发展没有问题。
解决办法
默认情况下,JSF 2 使用服务器进行会话管理,GAE 不支持(在 1.6.3 中测试)。要解决这个问题,更新 web.xml 文件,定义“javax.faces.STATE_SAVING_METHOD
,把值设为“客户端”。
文件:web.xml
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
参考
Mac OS X 上的 GAE + Python hello world
在本教程中,我们将向您展示如何在 Mac OS X 上使用 Python 创建一个简单的 GAE hello world web 项目,并通过 Google App Engine Launcher 运行它。
使用的工具:
- 用于 Python 的谷歌应用引擎 SDK(Mac OS X)-1 . 7 . 0
- 苹果 OS X 10.8
- Python 2.7
Note
By default, Mac OS X 10.8, has Python 2.7 installed, which makes Google App Engine development more easier.
1.谷歌应用引擎 SDK
访问这个Google App Engine SDK for Python,选择 Mac OS X 并开始下载。
1.1 安装 Google App Engine SDK
双击下载的GoogleAppEngineLauncher-version.dmg
文件,会提取出“ GoogleAppEngineLauncher ”图标,拖到你希望 GAE SDK 安装的文件夹中。
1.2 再次运行 Google App Engine Launcher
,双击“ GoogleAppEngineLauncher ”图标,按照向导提示完成安装。
图:Google appengine launcher–这个 GAE 启动器帮助你运行、部署和管理你的应用程序。
2.Python Hello World
File:hello . py–创建一个简单的 python 文件来显示 hello world 消息。
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Hello World, GAE + Python')
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
文件:app . YAML–创建一个简单的 GAE 配置文件。
application: helloworld
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: hello.app
完成了。
3.导入、运行和演示
在 GAE 启动程序中,两个手指点击表格网格->选择“添加已有… ”,找到上面包含 Python 文件的文件夹。
运行它并点击浏览以查看部署的 web 应用程序。
见演示:http://localhost:8888
下载源代码
Download it – gae-python-hello-world.zip (3 kb)
参考
在 Spring Security 中获取当前登录的用户名
在本文中,我们将向您展示在 Spring Security 中获取当前登录用户名的三种方法。
1.security context holder+authentic ation . getname()
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
@RequestMapping(value="/login", method = RequestMethod.GET)
public String printUser(ModelMap model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName(); //get logged in username
model.addAttribute("username", name);
return "hello";
}
//...
2.security context holder+user . get username()
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
@RequestMapping(value="/login", method = RequestMethod.GET)
public String printUser(ModelMap model) {
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String name = user.getUsername(); //get logged in username
model.addAttribute("username", name);
return "hello";
}
//...
3.usernamepasswordtauthenticationtoken
这是更优雅的解决方案,在运行时,Spring 会将UsernamePasswordAuthenticationToken
注入到Principal
接口中。
import java.security.Principal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
@RequestMapping(value="/login", method = RequestMethod.GET)
public String printWelcome(ModelMap model, Principal principal ) {
String name = principal.getName(); //get logged in username
model.addAttribute("username", name);
return "hello";
}
//...
下载源代码
Download it – Spring-Security-Get-Logged-In-Username.zip (9 KB)
参考
Tags : spring security
相关文章
使用 Eclipse 的 Google app engine Java hello world 示例
在本教程中,我们将向您展示如何使用 Eclipse 创建一个Google App Engine(GAE)Java项目(hello world 示例),在本地运行它,并将其部署到 Google App Engine 帐户。
使用的工具:
- JDK 1.6
- Eclipse 3.7+Eclipse 的 Google 插件
- 谷歌应用引擎 Java SDK 1.6.3.1
Note
GAE supports Java 1.5 and 1.6.
P.S 假设安装了 JDK1.6 和 Eclipse 3.7。
1.为 Eclipse 安装谷歌插件
阅读本指南-如何为 Eclipse 安装谷歌插件。如果你同时安装了 Google App Engine Java SDK 和“ Google Plugin for Eclipse ”,那么转到步骤 2,否则,获取 Google App Engine Java SDK 并解压。
2.创建新的 Web 应用程序项目
在 Eclipse 工具栏中,点击 Google 图标,选择“新建 Web 应用项目… ”
图-新的 Web 应用项目
图–取消选择“ Google Web ToolKit ”,通过“ configure SDK ”链接链接您的 GAE Java SDK。
单击 finished,Google Plugin for Eclipse 将自动生成一个示例项目。
3.你好世界
查看生成的项目目录。
没什么特别的,标准的 Java web 项目结构。
HelloWorld/
src/
...Java source code...
META-INF/
...other configuration...
war/
...JSPs, images, data files...
WEB-INF/
...app configuration...
lib/
...JARs for libraries...
classes/
...compiled classes...
额外的是这个文件“appengine-web.xml
”,Google App Engine 需要这个来运行和部署应用程序。
文件:appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application></application>
<version>1</version>
<!-- Configure java.util.logging -->
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>
4.在本地运行
右键单击项目并作为“ Web 应用程序”运行。
Eclipse 控制台:
//...
INFO: The server is running at http://localhost:8888/
30 Mac 2012 11:13:01 PM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The admin console is running at http://localhost:8888/_ah/admin
访问 URL http://localhost:8888/
,参见输出
还有 hello world servlet–http://localhost:8888/helloworld
5.部署到 Google 应用引擎
在https://appengine.google.com/上注册一个帐户,并为您的网络应用程序创建一个应用程序 ID。
在本演示中,我创建了一个名为“mkyong123”的应用程序 ID,并将其放在appengine-web.xml
中。
文件:appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application>mkyong123</application>
<version>1</version>
<!-- Configure java.util.logging -->
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>
要部署,请参见以下步骤:
图 1.1–点击工具栏上的 GAE 部署按钮。
图 1.2–使用您的 Google 帐户登录并点击部署按钮。
图 1.3–如果一切正常,hello world web 应用程序将被部署到这个 URL——http://mkyong123.appspot.com/
完成了。
参考
谷歌应用引擎+ JDO + Spring MVC,CRUD 例子
Note
This tutorial is more on practice guide, please refer to this official Using JDO in datastore for detail explanation.
参见下面的代码片段,使用 Java 数据对象(JDO) 在 GAE 数据存储上执行 CRUD。只需用 JDO 注释对客户进行注释,并通过 PersistenceManager 执行 CRUD。
增加
Customer c = new Customer();
c.setName(name);
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.makePersistent(c);
} finally {
pm.close();
}
搜索
搜索“客户”,其中 name = =“mkyong”。
PersistenceManager pm = PMF.get().getPersistenceManager();
Query q = pm.newQuery(Customer.class);
q.setFilter("name == nameParameter");
q.setOrdering("date desc");
q.declareParameters("String nameParameter");
try {
List<Customer> results = (List<Customer>) q.execute("mkyong");
//...
} finally {
q.closeAll();
pm.close();
}
搜索“客户”,其中 name = =“mkyong”,email = =“test @ Gmail . com”。
Query q = pm.newQuery(Customer.class);
q.setOrdering("date desc");
q.setFilter("name == nameParameter && email == emailParameter");
q.declareParameters("String nameParameter, String emailParameter");
try {
List<Customer> results = (List<Customer>) q.execute("mkyong", "[email protected]");
//...
} finally {
q.closeAll();
pm.close();
}
客户记录返回列表。
PersistenceManager pm = PMF.get().getPersistenceManager();
Query q = pm.newQuery(Customer.class);
q.setOrdering("date desc");
List<Customer> results = null;
try {
results = (List<Customer>) q.execute();
if (!results.isEmpty()) {
// good for listing
}
} finally {
q.closeAll();
pm.close();
}
更新
若要更新,请获取现有对象并修改它。
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Customer c = pm.getObjectById(Customer.class, key);
c.setName(name);
c.setEmail(email);
c.setDate(new Date());
} finally {
pm.close();
}
删除
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Customer c = pm.getObjectById(Customer.class, key);
pm.deletePersistent(c);
} finally {
pm.close();
}
GAE + Spring MVC + CRUD 示例
好了,现在我们将向您展示一个使用 Spring MVC 以 REST 风格开发的简单 web 应用程序,它使用 JDO 在 datastore 中存储数据。
- 谷歌应用引擎 Java SDK 1.6.3.1,JDO 2.3
- 弹簧 3.1.1
- JDK 1.6
- Eclipse 3.7+Eclipse 的 Google 插件
另外,使用 Google Plugin for Eclipse 创建一个 web 应用程序项目模板,它会自动为您创建和配置jdoconfig.xml
。
Note
This example is keep into as simple as possible, to show you how to use JDO to perform CRUD only, no layers like DAO or BO, no validation or message notification of the success or failed action.
1.顾客
用 JDO 注释来注释客户对象。
package com.mkyong.model;
import java.util.Date;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
@PersistenceCapable
public class Customer {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private String name;
@Persistent
private String email;
@Persistent
private Date date;
//getter and setter methods
}
2.持久性管理器
创建一个 singleton PersistenceManager 类。
package com.mkyong;
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;
}
}
3.弹簧控制器
弹簧控制器,REST 风格,执行 CRUD 操作。代码应该是不言自明的。
文件:CustomerController.java
package com.mkyong.controller;
import java.util.Date;
import java.util.List;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.mkyong.PMF;
import com.mkyong.model.Customer;
@Controller
@RequestMapping("/customer")
public class CustomerController {
@RequestMapping(value = "/add", method = RequestMethod.GET)
public String getAddCustomerPage(ModelMap model) {
return "add";
}
@RequestMapping(value = "/add", method = RequestMethod.POST)
public ModelAndView add(HttpServletRequest request, ModelMap model) {
String name = request.getParameter("name");
String email = request.getParameter("email");
Customer c = new Customer();
c.setName(name);
c.setEmail(email);
c.setDate(new Date());
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
pm.makePersistent(c);
} finally {
pm.close();
}
return new ModelAndView("redirect:list");
}
@RequestMapping(value = "/update/{name}", method = RequestMethod.GET)
public String getUpdateCustomerPage(@PathVariable String name,
HttpServletRequest request, ModelMap model) {
PersistenceManager pm = PMF.get().getPersistenceManager();
Query q = pm.newQuery(Customer.class);
q.setFilter("name == nameParameter");
q.setOrdering("date desc");
q.declareParameters("String nameParameter");
try {
List<Customer> results = (List<Customer>) q.execute(name);
if (results.isEmpty()) {
model.addAttribute("customer", null);
} else {
model.addAttribute("customer", results.get(0));
}
} finally {
q.closeAll();
pm.close();
}
return "update";
}
@RequestMapping(value = "/update", method = RequestMethod.POST)
public ModelAndView update(HttpServletRequest request, ModelMap model) {
String name = request.getParameter("name");
String email = request.getParameter("email");
String key = request.getParameter("key");
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Customer c = pm.getObjectById(Customer.class, key);
c.setName(name);
c.setEmail(email);
c.setDate(new Date());
} finally {
pm.close();
}
// return to list
return new ModelAndView("redirect:list");
}
@RequestMapping(value = "/delete/{key}", method = RequestMethod.GET)
public ModelAndView delete(@PathVariable String key,
HttpServletRequest request, ModelMap model) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
Customer c = pm.getObjectById(Customer.class, key);
pm.deletePersistent(c);
} finally {
pm.close();
}
// return to list
return new ModelAndView("redirect:../list");
}
// get all customers
@RequestMapping(value = "/list", method = RequestMethod.GET)
public String listCustomer(ModelMap model) {
PersistenceManager pm = PMF.get().getPersistenceManager();
Query q = pm.newQuery(Customer.class);
q.setOrdering("date desc");
List<Customer> results = null;
try {
results = (List<Customer>) q.execute();
if (results.isEmpty()) {
model.addAttribute("customerList", null);
} else {
model.addAttribute("customerList", results);
}
} finally {
q.closeAll();
pm.close();
}
return "list";
}
}
4.JSP 页面
显示客户并执行添加、更新和删除的 JSP 页面。
文件:list.jsp
<%@ page import="java.util.List" %>
<%@ page import="com.mkyong.model.Customer" %>
<%@ page import="com.google.appengine.api.datastore.KeyFactory" %>
<html>
<body>
<h1>GAE + Spring 3 MVC REST + CRUD Example with JDO</h1>
Function : <a href="add">Add Customer</a>
<hr />
<h2>All Customers</h2>
<table border="1">
<thead>
<tr>
<td>Name</td>
<td>Email</td>
<td>Created Date</td>
<td>Action</td>
</tr>
</thead>
<%
if(request.getAttribute("customerList")!=null){
List<Customer> customers =
(List<Customer>)request.getAttribute("customerList");
if(!customers.isEmpty()){
for(Customer c : customers){
%>
<tr>
<td><%=c.getName() %></td>
<td><%=c.getEmail() %></td>
<td><%=c.getDate() %></td>
<td><a href="update/<%=c.getName()%>">Update</a> |
<a href="delete/<%=KeyFactory.keyToString(c.getKey()) %>">
Delete</a>
</td>
</tr>
<%
}
}
}
%>
</tr>
</table>
</body>
</html>
文件:add.jsp
<html>
<body>
<h1>Add Customer</h1>
<form method="post" action="add">
<table>
<tr>
<td>UserName :</td>
<td><input type="text" style="width: 185px;" maxlength="30"
name="name" id="name" /></span></td>
</tr>
<tr>
<td>Email :</td>
<td><input type="text" style="width: 185px;" maxlength="30"
name="email" id="email" /></span></td>
</tr>
</table>
<input type="submit" class="save" title="Save" value="Save" />
</form>
</body>
</html>
文件:update.jsp
<%@ page import="com.mkyong.model.Customer" %>
<%@ page import="com.google.appengine.api.datastore.KeyFactory" %>
<html>
<body>
<h1>Update Customer</h1>
<%
Customer customer = new Customer();
if(request.getAttribute("customer")!=null){
customer = (Customer)request.getAttribute("customer");
}
%>
<form method="post" action="../update" >
<input type="hidden" name="key" id="key"
value="<%=KeyFactory.keyToString(customer.getKey()) %>" />
<table>
<tr>
<td>
UserName :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="name" id="name"
value="<%=customer.getName() %>" />
</td>
</tr>
<tr>
<td>
Email :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="email" id="email"
value="<%=customer.getEmail() %>" />
</td>
</tr>
</table>
<input type="submit" class="update" title="Update" value="Update" />
</form>
</body>
</html>
5.演示
完成,看 demo 向你展示 web 应用的工作流程。
1.列表页面,显示现有客户列表。
网址:http://localhost:8888/customer/list
2.在列表页面中,点击“添加客户”链接,显示添加客户页面,填写新客户,姓名= " mkyong ",邮箱= “【[email protected]】”,点击“添加”按钮。
网址:http://localhost:8888/customer/add
3.保存了客户,就会返回到列表页面。
网址:http://localhost:8888/customer/list
4.尝试更新链接,它将显示所选客户的数据,更新电子邮件至“[email protected]”,并点击更新按钮。
网址:http://localhost:8888/customer/update/mkyong
5.电子邮件被更新,并重定向回列表页面。
网址:http://localhost:8888/customer/list
6.要删除客户,只需点击“删除”链接。
下载源代码
由于文件很大,所有 Spring MVC 和 GAE jar 都被排除在外。
Download – GAE-SpringMVC-JDO-example.zip (22 KB)
参考
谷歌应用引擎+ JSF 2 的例子
在本教程中,我们将向您展示如何在谷歌应用引擎(GAE)环境中开发和部署 JSF 2.0 web 应用程序。
使用的工具和技术:
- JDK 1.6
- Eclipse 3.7+Eclipse 的 Google 插件
- 谷歌应用引擎 Java SDK 1.6.3.1
- JSF 2.1.7
Note
This example is going to reuse this JSF 2.0 hello world example, modify it and merge it with this GAE + Java example.
1.新建 Web 应用程序项目
在 Eclipse 中,创建一个新的 Web 应用项目,命名为“ JSFGoogleAppEngine ”。
“谷歌 Eclipse 插件”将生成一个 GAE 项目结构的样本。
2.JSF 新协议的附属协议
要在 GAE 使用 JSF 2,你需要以下罐子
- jsf-api-2.1.7.jar
- jsf-impl-2.1.7.jar
- 埃尔里-1.0.jar
复制后放入“ war/WEB-INF/lib ”文件夹。
右击项目文件夹,选择“属性”。选择“ Java 构建路径->-库”选项卡,点击“添加 Jars 按钮,选择上面的 Jars。
Note
You need to put this el-ri-1.0.jar
, otherwise, you will hit error message – Unable to instantiate ExpressionFactory ‘com.sun.el.ExpressionFactoryImpl’.
3.JSF 管理比恩
3.1 删除插件生成的JSFGoogleAppEngineServlet.java
,不需要这个。
3.2 创建一个受管理的 bean。
文件:src/com/mkyong/hello bean . Java
package com.mkyong;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
@ManagedBean
@SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.3 创建一个新的 WebConfiguration.java。
JSF 2 号正在使用“javax.naming.InitialContext
”这在 GAE 是不支持的。
要解决这个问题,你需要得到一份 JSF 的源代码,克隆出WebConfiguration.java
,注释正在使用javax.naming.InitialContext
类的方法,把它放在src/com/sun/faces/com fig/web configuration . Java。现在,您新创建的WebConfiguration.java
类将重载原来的WebConfiguration.java
。
Note
Get the full source code of the WebConfiguration.java.
我不认为 GAE 团队会白名单这个罐子,只是希望 JSF 的团队可以在未来的版本中修复这个问题。
4.JSF 页面
4.1 创建hello.xhtml
页面,接受用户输入并将其传递给 helloBean。
文件:war/hello.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>GAE + JSF</title>
</h:head>
<h:body>
<h1>Google App Engine + JSF 2.0 example - hello.xhtml</h1>
<h:form>
<h:inputText value="#{helloBean.name}"></h:inputText>
<h:commandButton value="Welcome Me" action="welcome"></h:commandButton>
</h:form>
</h:body>
</html>
4.2 创建welcome.xhtml
页面,显示来自 hellobean 的用户输入。
文件:war/welcome.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>GAE + JSF</title>
</h:head>
<h:body bgcolor="white">
<h1>Google App Engine + JSF 2.0 example - welcome.xhtml</h1>
<h2>Welcome #{
helloBean.name}</h2>
</h:body>
</html>
4.3 删除插件生成的index.html
文件,你不需要这个。
5.web.xml
更新 web.xml,集成 JSF 2。
文件:web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<display-name>JavaServerFaces</display-name>
<!-- GAE 1.6.3 cannot handle server side (JSF default) state management. -->
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<!-- Change to "Production" when you are ready to deploy -->
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- Welcome page -->
<welcome-file-list>
<welcome-file>faces/hello.xhtml</welcome-file>
</welcome-file-list>
<!-- JSF mapping -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map these files with JSF -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
Note
GAE do not support server side state management, so, you need to define “javax.faces.STATE_SAVING_METHOD
” to “client
“, to avoid of this “View /hello.xhtml could not be restored” error message in GAE production environment.
6.在 GAE 启用会话
更新appengine-web.xml
,启用会话支持,JSF 需要这个。
文件:appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application></application>
<version>1</version>
<sessions-enabled>true</sessions-enabled>
</appengine-web-app>
7.目录结构
审查最终目录结构。
8.在本地运行
右键单击项目,作为“Web 应用程序”运行。
网址:http://localhost:8888/hello . JSF
点击按钮。
10.部署在 GAE
更新appengine-web.xml
文件,添加您的 App Engine 应用 ID。
文件:appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application>mkyong-jsf2gae</application>
<version>1</version>
<sessions-enabled>true</sessions-enabled>
</appengine-web-app>
选择项目,点击谷歌图标,“部署到应用引擎”。
网址:http://mkyong-jsf2gae.appspot.com/hello.jsf
下载源代码
由于文件很大,所有 JSF 和 GAE 的罐子都被排除在外。
Download – JSF2-GoogleAppEngine-Example.zip (42 KB)
参考
- JSF 和 GAE 兼容问题
- 谷歌应用上的 JSF 2 配置
- 带 JSF 2 + CDI 的谷歌应用引擎
- 开始使用谷歌应用和 JSF
- JSF 2.0 hello world 示例
- Oracle : JavaServer Faces 开发教程
相关文章
使用 Eclipse 的 Google app engine Python hello world 示例
在本教程中,我们将向您展示如何使用 Eclipse 创建一个Google App Engine(GAE)Pythonweb 项目(hello world 示例),在本地运行它,并将其部署到 Google App Engine 帐户。
使用的工具:
- Python 2.7
- Eclipse 3.7 + PyDev 插件
- 用于 Python 1.6.4 的谷歌应用引擎 SDK
P.S 假设安装了 Python 2.7 和 Eclipse 3.7。
1.为 Eclipse 安装 PyDev 插件
使用下面的 URL 安装 PyDev 作为 Eclipse 插件。
http://pydev.org/updates
图 1——在 Eclipse 菜单中,“帮助—>安装新软件。”并放在上面的网址。选择“ PyDev for Eclipse ”选项,按照步骤操作,并在完成后重启 Eclipse。
2.验证 PyDev
Eclipse 重启后,确保 PyDev 的解释器指向你的python.exe
。
图 2-Eclipse->-Windows->首选项,确保“解释器-Python配置正确。
3.谷歌应用引擎 SDK Python
下载并安装Google App Engine SDK for Python。
4.Eclipse 中的 Python Hello World
下面的步骤向你展示了如何通过 Pydev 插件创建一个 GAE 项目。
图 4.1–Eclipse 菜单,文件- >新建- >其他…,PyDev 文件夹,选择“ PyDev Google App Engine 项目”。
图 4.2–键入项目名称,如果解释器尚未配置(在步骤 2 中),您现在可以这样做。并选择此选项—“创建‘src’文件夹并将其添加到 PYTHONPATH ”。
图 4.3–点击“浏览”按钮,指向 Google App Engine 安装目录(在步骤 3 中)。
图 4.4–在 GAE 命名您的应用程序 id,键入任何内容,您可以稍后更改。并选择“ Hello Webapp World 模板生成示例文件。
图 4.5–完成,生成 4 个文件,.pydevproject
、.project
都是 Eclipse 项目文件,忽略。
查看生成的 Python 文件:
File:helloworld . py——只输出一个 hello world。
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class MainPage(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Hello, webapp World!')
application = webapp.WSGIApplication([('/', MainPage)], debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
文件:app . YAML–GAE 需要这个文件来运行和部署你的 Python 项目,它非常简单明了,详细的语法和配置,请访问 yaml 和 app.yaml 参考。
application: mkyong-python
version: 1
runtime: python
api_version: 1
handlers:
- url: /.*
script: helloworld.py
5.在本地运行
要在本地运行它,右击helloworld.py
,选择“运行方式”—>“运行配置”,创建一个新的“ PyDev Google App 运行”。
图 5.1-在主选项卡- >主模块中,手动键入“ dev_appserver.py 的目录路径。“浏览”按钮不能够帮助你,手动输入。
图 5.2–在“参数”选项卡- >程序参数中,填入“ ${project_loc}/src ”。
图 5.3–运行它。默认情况下,它会部署到 http://localhost:8080 。
图 5.4–完成。
5.部署到 Google 应用引擎
在https://appengine.google.com/上注册一个账户,并为你的网络应用创建一个应用 ID。再次回顾“app.yaml
”,这个 web 应用程序将被部署到 GAE,应用程序 ID 为“ mkyong-python ”。
文件:app.yaml
application: mkyong-python
version: 1
runtime: python
api_version: 1
handlers:
- url: /.*
script: helloworld.py
要部署到 GAE,请参见以下步骤:
图 5.1-新建一个“PyDev Google App Run”,在主选项卡- >主模块中,手动键入“ appcfg.py 的目录路径。
图 5.2–在参数选项卡- >程序参数中,放入“更新${project_loc}/src ”。
图 5.3–在部署过程中,您需要输入您的 GAE 电子邮件和密码进行验证。
图 5.4-如果成功,web app 将部署到 http://mkyong-python.appspot.com/。
*
完成了。
参考
- 用于 Eclipse 的 PyDev 插件
- Yaml 官网
- GAE 开始使用 Python
- 为 Eclipse 安装 PyDev】
- GAE Java hello world 使用 Eclipse 的例子
*
Google App Engine + Spring 3 MVC REST 示例
在本教程中,我们将向您展示如何在 Google App Engine()环境中开发和部署一个 Spring 3.0 MVC REST web 应用程序。
**使用的工具和技术:
- 谷歌应用引擎 Java SDK 1.6.3.1
- 弹簧 3.1.1
- JDK 1.6
- Eclipse 3.7+Eclipse 的 Google 插件
Note
This example is going to reuse this Spring 3 MVC REST example, modify it and integrate with Google App Engine, you may also interest to read this – GAE + Java + Eclipse example
1.新建 Web 应用程序项目
在 Eclipse 中,创建一个新的 Web 应用项目,命名为“ SpringMVCGoogleAppEngine ”。
Eclipse 的“ Google 插件将生成一个 GAE 项目结构的样本。
2.Spring 3.0 依赖项
要在 GAE 使用 Spring MVC + REST ,您需要以下 jar
- aopalliance-1.0.jar
- commons-logging-1.1.1.jar
- spring-aop-3.1.1
- spring-asm-3.1.1 .版本. jar
- spring-beans-3.1.1.RELEASE.jar
- spring 上下文 3.1.1.RELEASE.jar
- spring-context-support-3.1.1
- 3.1.1.RELEASE.jar
- spring-表达式-3.1.1.RELEASE.jar
- spring-web-3.1.1.RELEASE.jar
- spring-webmvc-3.1.1
复制后放入“ war/WEB-INF/lib ”文件夹。
将其添加到项目的构建路径中——右键单击项目文件夹,选择“ Properties ”。选择“ Java 构建路径->-库”选项卡,点击“添加 Jars 按钮,选择上面的 Jars。
## 3.弹簧控制器
3.1 删除自动生成的SpringMVCGoogleAppEngineServlet.java
,不需要这个。
3.2 创建一个 bean,在 REST 结构中充当控制器。此外,阿迪的消息进入了“message
”属性。
文件:src/com/mkyong/movie controller . Java
package com.mkyong.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("/movie")
public class MovieController {
//DI via Spring
String message;
@RequestMapping(value="/{name}", method = RequestMethod.GET)
public String getMovie(@PathVariable String name, ModelMap model) {
model.addAttribute("movie", name);
model.addAttribute("message", this.message);
//return to jsp page, configured in mvc-dispatcher-servlet.xml, view resolver
return "list";
}
public void setMessage(String message) {
this.message = message;
}
}
4.JSP 页面
创建一个list.jsp
页面,显示结果。
文件:war/list.jsp
<html>
<body>
<h1>GAE + Spring 3 MVC REST example</h1>
<h2>Movie : ${
movie} , DI message : ${
message}</h2>
</body>
</html>
5.弹簧配置
创建一个 Spring XML bean 配置文件,定义 bean 并查看解析器。
文件:war/we b-INF/MVC-dispatcher-servlet . XML
<beans
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!--
Need DI a message into controller, so auto component scan is disabled,
to avoid double create the movieController bean.
Only controller need this hack.
-->
<context:component-scan base-package="com.mkyong.controller">
<context:exclude-filter type="regex"
expression="com.mkyong.controller.Movie.*" />
</context:component-scan>
<mvc:annotation-driven />
<!-- Bean to show you Di in GAE, via Spring, also init the MovieController -->
<bean class="com.mkyong.controller.MovieController">
<property name="message">
<value>Hello World</value>
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
6.web.xml
更新web.xml
,集成 Spring 框架。
文件:war/WEB-INF/web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
7.目录结构
查看最终的目录结构。
8.在本地运行
右键点击项目,运行为“ Web 应用”。
网址:http://localhost:8888/movie/Avengers
9.部署在 GAE
更新appengine-web.xml
文件,添加您的 App Engine 应用 ID。
文件:war/we b-INF/app engine-WEB . XML
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application>mkyong-springmvc</application>
<version>1</version>
<system-properties>
<property name="java.util.logging.config.file"
value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>
选择项目,点击谷歌图标,“部署到应用引擎”。
网址:http://mkyong-springmvc.appspot.com/movie/forrest%20gump
下载源代码
由于文件较大,所有 Spring 和 GAE jar 都被排除在外。
Download – SpringMVC-GoogleAppEngine.zip (12 KB)
参考
- 春天 3.0 豆子参考
- REST 解释维基百科
- Google App Engine+Java+Google Plugin for eclipse 示例
- Spring 3 MVC hello world 示例
- 春天 3 休息你好世界示例
- Google 添加引擎 Java doc
gae rest spring mvc spring rest
Google App Engine + Spring MVC,带有数据存储低级 api 的 CRUD 示例
GAE datastore
Refer to this official “Using datstore guide” to understand what is GAE datastore.
参见以下代码片段,使用低级 API 为 Google App Engine datastore,Java 执行 CRUD。
增加
将客户存储到数据存储中,以“name”作为键。
Key customerKey = KeyFactory.createKey("Customer", "your name");
Entity customer = new Entity("Customer", customerKey);
customer.setProperty("name", "your name");
customer.setProperty("email", "your email");
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(customer); //save it
搜索
返回 10 个客户作为列表。
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("Customer").addSort("date", Query.SortDirection.DESCENDING);
List<Entity> customers = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));
用匹配的过滤器找到并返回一个客户。
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, "your name");
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
FilterOperator.EQUAL
Play this filters, it has few condition options, like less than, great than and etc.
更新
要更新,只需修改现有实体并再次保存即可。
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, "your name");
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
customer.setProperty("name", name);
customer.setProperty("email", email);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(customer); //GAE will know save or update
删除
要删除,需要实体键。
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, name);
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.delete(customer.getKey()); //delete it
GAE + Spring MVC + CRUD 示例
好了,现在我们将向您展示一个使用 Spring MVC 以 REST 风格开发的简单 web 应用程序,操作 Google App Engine datastore 中的数据,使用上面的低级 API。
- 谷歌应用引擎 Java SDK 1.6.3.1
- 弹簧 3.1.1
- JDK 1.6
- Eclipse 3.7+Eclipse 的 Google 插件
Note
This example is keep into as simple as possible, to show you how to perform CRUD only, no layers like DAO or BO, no validation or message notification of the success or failed action.
1.弹簧控制器
Spring 控制器,REST 风格,用于显示网页和执行 CRUD。代码应该是不言自明的。
文件:CustomerController.java
package com.mkyong.controller;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
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.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
@Controller
@RequestMapping("/customer")
public class CustomerController {
@RequestMapping(value="/addCustomerPage", method = RequestMethod.GET)
public String getAddCustomerPage(ModelMap model) {
return "add";
}
@RequestMapping(value="/add", method = RequestMethod.POST)
public ModelAndView add(HttpServletRequest request, ModelMap model) {
String name = request.getParameter("name");
String email = request.getParameter("email");
Key customerKey = KeyFactory.createKey("Customer", name);
Date date = new Date();
Entity customer = new Entity("Customer", customerKey);
customer.setProperty("name", name);
customer.setProperty("email", email);
customer.setProperty("date", date);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(customer);
return new ModelAndView("redirect:list");
}
@RequestMapping(value="/update/{name}", method = RequestMethod.GET)
public String getUpdateCustomerPage(@PathVariable String name,
HttpServletRequest request, ModelMap model) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, name);
PreparedQuery pq = datastore.prepare(query);
Entity e = pq.asSingleEntity();
model.addAttribute("customer", e);
return "update";
}
@RequestMapping(value="/update", method = RequestMethod.POST)
public ModelAndView update(HttpServletRequest request, ModelMap model) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
String name = request.getParameter("name");
String email = request.getParameter("email");
String originalName = request.getParameter("originalName");
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, originalName);
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
customer.setProperty("name", name);
customer.setProperty("email", email);
customer.setProperty("date", new Date());
datastore.put(customer);
//return to list
return new ModelAndView("redirect:list");
}
@RequestMapping(value="/delete/{name}", method = RequestMethod.GET)
public ModelAndView delete(@PathVariable String name,
HttpServletRequest request, ModelMap model) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, name);
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
datastore.delete(customer.getKey());
//return to list
return new ModelAndView("redirect:../list");
}
//get all customers
@RequestMapping(value="/list", method = RequestMethod.GET)
public String listCustomer(ModelMap model) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query =
new Query("Customer").addSort("date", Query.SortDirection.DESCENDING);
List<Entity> customers =
datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));
model.addAttribute("customerList", customers);
return "list";
}
}
2.JSP 页面
3 个 JSP 页面来显示客户并执行添加和更新。
文件:list.jsp
<%@ page import="java.util.List" %>
<%@ page import="com.google.appengine.api.datastore.Entity" %>
<html>
<body>
<h1>GAE + Spring 3 MVC REST + CRUD Example</h1>
Function : <a href="addCustomerPage">Add Customer</a>
<hr />
<h2>All Customers</h2>
<table border="1">
<thead>
<tr>
<td>Name</td>
<td>Email</td>
<td>Created Date</td>
<td>Action</td>
</tr>
</thead>
<%
List<Entity> customers = (List<Entity>)request.getAttribute("customerList");
for(Entity e : customers){
%>
<tr>
<td><%=e.getProperty("name") %></td>
<td><%=e.getProperty("email") %></td>
<td><%=e.getProperty("date") %></td>
<td><a href="update/<%=e.getProperty("name")%>">Update</a>
| <a href="delete/<%=e.getProperty("name")%>">Delete</a></td>
</tr>
<%
}
%>
</table>
</body>
</html>
文件:add.jsp
<html>
<body>
<h1>Add Customer</h1>
<form method="post" action="add" >
<table>
<tr>
<td>
UserName :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="name" id="name" />
</td>
</tr>
<tr>
<td>
Email :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="email" id="email" />
</td>
</tr>
</table>
<input type="submit" class="save" title="Save" value="Save" />
</form>
</body>
</html>
文件:update.jsp
<%@ page import="com.google.appengine.api.datastore.Entity" %>
<html>
<body>
<h1>Update Customer</h1>
<%
Entity customer = (Entity)request.getAttribute("customer");
%>
<form method="post" action="../update" >
<input type="hidden" name="originalName" id="originalName"
value="<%=customer.getProperty("name") %>" />
<table>
<tr>
<td>
UserName :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="name" id="name"
value="<%=customer.getProperty("name") %>" />
</td>
</tr>
<tr>
<td>
Email :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="email" id="email"
value="<%=customer.getProperty("email") %>" />
</td>
</tr>
</table>
<input type="submit" class="update" title="Update" value="Update" />
</form>
</body>
</html>
3.弹簧配置
扫描 Spring 控制器并配置视图解析器,以便它可以将视图重定向到 jsp 页面。
文件:mvc-dispatcher-servlet.xml
<beans
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.mkyong.controller" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
4.集成弹簧
将 Spring 集成到 web 应用程序中。
文件:web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
5.演示
完成,看 demo,向你展示 web 应用的工作流程。
1.列表页面,显示现有客户列表。
网址:http://localhost:8888/customer/list
2.在列表页面中,点击“添加客户”链接以显示添加客户页面,填写新客户,并点击“添加”按钮。
URL : http://localhost:8888/customer/addCustomerPage
3.保存了客户后,它会返回到列表页面。
网址:http://localhost:8888/customer/list
4.尝试更新链接,它将显示所选客户的数据,更新电子邮件地址并点击更新按钮。
网址:http://localhost:8888/customer/update/mkyong
5.电子邮件被更新,并重定向回列表页面。
网址:http://localhost:8888/customer/list
6.要删除客户,只需点击“删除”链接。
下载源代码
由于文件很大,所有 Spring MVC 和 GAE jar 都被排除在外。
Download – GoogleAppEngine-SpringMVC-datastore.zip (17 KB)
参考
- GAE:使用数据存储
- GAE:实体
- GAE:数据存储低层 api
- GAE:JDO 和 Spring MVC 的 CRUD 操作
- 使用 Google App Engine、Spring MVC 和 Flex 的体验
Google 应用引擎+ Struts 1 示例
经典 Struts 1 框架万岁,在本教程中,我们将向您展示如何在 Google App Engine (GAE)环境下开发一个 Struts 1.x web 应用。
使用的工具和技术:
- JDK 1.6
- Eclipse 3.7+Eclipse 的 Google 插件
- 谷歌应用引擎 Java SDK 1.6.3.1
- Struts 1.3.10
Note
You may also interest at this Google App Engine + Struts 2 example.
这个例子将把 Struts 1.x hello world 例子与这个 GAE + Java 例子合并。
1.新建 Web 应用程序项目
在 Eclipse 中,创建一个新的 Web 应用程序项目,命名为“StrutsGoogleAppEngine”。
Google Plugin for Eclipse 将生成一个样本 GAE 项目结构。稍后将把 Struts 1 集成到这个 GAE 结构中。
2.集成 Struts 1.x 库
访问此链接下载 Struts 1.x 。需要以下罐子:
- antlr-2.7.2.jar
- commons-beanutils-1.8.0.jar
- 公共链 1.2.jar
- 1.8.jar
- commons-logging-1.0.4.jar
- 公共验证器 1.3.1.jar
- 奥罗-2.0.8.jar
- struts-core-1.3.10.jar
- struts-taglib-1.3.10.jar
复制后放入“ war/WEB-INF/lib ”文件夹。
右击项目文件夹,选择属性。选择" Java 构建路径 " - > " 库"选项卡,点击"添加 Jars “按钮,从” war/WEB-INF/lib "文件夹中选择上面 9 个 Jars 进入构建路径。
## 3.集成 Struts 1.x 动作和表单
3.1 删除StrutsGoogleAppEngineServlet.java
,你不需要这个。
3.2 创建新的操作类。
文件:src/com/mkyong/action/hello world action . Java
package com.mkyong.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.mkyong.form.HelloWorldForm;
public class HelloWorldAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
HelloWorldForm helloWorldForm = (HelloWorldForm) form;
helloWorldForm.setMessage("Hello World!");
return mapping.findForward("success");
}
}
3.3 创建一个新的表单类。
文件:src/com/mkyong/form/hello world form . Java
package com.mkyong.form;
import org.apache.struts.action.ActionForm;
public class HelloWorldForm extends ActionForm {
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
4.集成 Struts 1.x JSP 页面
4.1 创建HelloWorld.jsp
页面,放入“war/User/pages/hello world . JSP”。
文件:HelloWorld.jsp
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<html>
<head>
</head>
<body>
<h1>
Google App Engine + Struts 1.x example
</h1>
<h2><bean:write name="helloWorldForm" property="message" /></h2>
</body>
</html>
5.Struts XML 配置
创建一个struts-config.xml
文件,放在“war/we b-INF/struts-config . XML”中。
文件:struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">
<struts-config>
<form-beans>
<form-bean name="helloWorldForm" type="com.mkyong.form.HelloWorldForm" />
</form-beans>
<action-mappings>
<action path="/helloWorld" type="com.mkyong.action.HelloWorldAction"
name="helloWorldForm">
<forward name="success" path="/HelloWorld.jsp" />
</action>
</action-mappings>
</struts-config>
6.web.xml
更新web.xml
,整合 Struts。
文件:web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
7.在 GAE 启用会话
更新appengine-web.xml
,启用会话支持,Struts 需要这个。
文件:appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application></application>
<version>1</version>
<sessions-enabled>true</sessions-enabled>
</appengine-web-app>
Note
If you don’t enable session in GAE, you will hit error “java.lang.RuntimeException: Session support is not enabled in appengine-web.xml“.
8.目录结构
查看最终的目录结构。
9.在本地运行
右键点击项目,运行为“ Web 应用”。
网址:http://localhost:8888/hello world . do
10.部署在 GAE
更新appengine-web.xml
文件,添加您的 App Engine 应用 ID。
文件:appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application>mkyong-strutsgae</application>
<version>1</version>
<sessions-enabled>true</sessions-enabled>
</appengine-web-app>
选择项目,点击谷歌图标,“部署到应用引擎”。
网址:http://mkyong-strutsgae.appspot.com/helloWorld.do
Note
Not much problem, just follow GAE directory structure, at least integrate Struts 1 is more easily than Struts 2.
下载源代码
由于文件较大,所有 Struts1 jars 都被排除在外,需要手动下载。
Download – StrutsGoogleAppEngine (13 KB)
参考
Google 应用引擎+ Struts 2 示例
在本教程中,我们将向您展示如何在 Google App Engine (GAE)环境下开发 Struts 2 web 应用程序。
使用的工具和技术:
- JDK 1.6
- Eclipse 3.7+Eclipse 的 Google 插件
- 谷歌应用引擎 Java SDK 1.6.3.1
- struts 2.3.1.2
Note
Before proceed on this tutorial, make sure you read this – GAE + Java example and Struts 2 hello world example.
1.新建 Web 应用程序项目
在 Eclipse 中,创建一个新的 Web 应用程序项目,命名为“Struts2GoogleAppEngine”。
Eclipse 的谷歌插件将生成一个 GAE 项目结构的样本。稍后,我们将向您展示如何将 Struts2 与这个生成的 GAE 项目集成。
## 2.集成 Struts 2 库
获取以下 Struts 2 依赖库,在此下载 Struts 2。
- asm-3.3.jar
- asm-commons-3.3
- 组件树 3.3.jar
- 文件上传-1.2.2.jar
- commons-io-2.0.1.jar
- 2.5.jar
- 自由标记-2.3.18.jar
- javassist-3.11.0.GA.jar
- ognl-3.0.4.jar
- 支柱 2-核心-2.3.1.2.jar
- xwork-core-2.3.1.2.jar
全部放入“ war/WEB-INF/lib ”文件夹。
右键点击项目文件夹,选择"属性 " - > " Java 构建路径 " - > " 库"选项卡,点击"添加 Jars 按钮,从" war/WEB-INF/lib "文件夹中选择以上 11 个 Jars 进入构建路径。
## 3.集成 Struts 2 代码
3.1 删除生成的Struts2GoogleAppEngineServlet.java
,不需要这个。
3.2 创建一个新的 Struts 2 操作类。
文件:src/com/mkyong/user/action/welcome user action . Java
package com.mkyong.user.action;
public class WelcomeUserAction {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String execute() {
return "SUCCESS";
}
}
3.3 创建一个监听器类,并将 ognl 安全设置为空。
Note
Struts 2 need this listener to run in GAE environment. Read this – Issues when deploying Struts 2 on GAE and Error: result ‘null’ not found
文件:src/com/mkyong/listener/struts 2 listenerongae . Java
package com.mkyong.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import ognl.OgnlRuntime;
public class Struts2ListenerOnGAE implements ServletContextListener,
HttpSessionListener, HttpSessionAttributeListener {
public void contextInitialized(ServletContextEvent sce) {
OgnlRuntime.setSecurityManager(null);
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void sessionCreated(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void attributeAdded(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void attributeRemoved(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}
}
3.4 要在本地 GAE 环境中运行 Struts2 项目,必须创建一个TextBlock
类,并重载原来的TextBlok
类,否则会出现“javax.swing.tree.TreeNode is a restricted class
错误信息。希望 Struts2 团队可以在未来的版本中解决这个问题。
TextBlock Source Code
Go this URL to download TextBlock source code.
3.5 审查项目目录结构。
4.集成 Struts 2 页
4.1 创建一个login.jsp
页面,接受用户输入。
文件:war/User/pages/login.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head></head>
<body>
<h1>GAE + Struts 2 Example</h1>
<s:form action="Welcome">
<s:textfield name="username" label="Username"/>
<s:password name="password" label="Password"/>
<s:submit/>
</s:form>
</body>
</html>
4.2 创建一个welcome_user.jsp
页面。
文件:war/User/pages/welcome _ User . JSP
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head></head>
<body>
<h1>GAE + Struts 2 Example</h1>
<h2>Hello <s:property value="username"/></h2>
</body>
</html>
4.3 再次审查项目目录结构。
5.Struts XML 配置
创建一个struts.xml
文件,放入“ src/struts.xml ”。
文件:struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="user" namespace="/User" extends="struts-default">
<action name="Login">
<result>pages/login.jsp</result>
</action>
<action name="Welcome" class="com.mkyong.user.action.WelcomeUserAction">
<result name="SUCCESS">pages/welcome_user.jsp</result>
</action>
</package>
</struts>
6.web.xml
更新web.xml
,集成 Struts2,配置 ognl 安全监听器。
文件:web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
com.mkyong.listener.Struts2ListenerOnGAE
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
7.目录结构
查看最终的目录结构。
8.在本地运行
完成,是时候进行测试了。右键点击项目,运行为“ Web 应用”。
网址:http://localhost:8888/User/log in . action
9.部署在 GAE
更新appengine-web.xml
,放上你的 App Engine 应用 ID。
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app >
<application>mkyong-struts2gae</application>
<version>1</version>
<!-- Configure java.util.logging -->
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>
选择项目,点击谷歌图标,“部署到应用引擎”。谷歌 Eclipse 插件将自动部署所有必要的文件到 GAE 生产。
在部署期间,Eclipse 控制台视图中将显示以下类似的消息。
------------ Deploying frontend ------------
Preparing to deploy:
Created staging directory at: 'C:\Users\mkyong\AppData\Local\Temp\appcfg7432687551.tmp'
Scanning for jsp files.
Compiling jsp files.
Scanning files on local disk.
Initiating update.
Cloning 2 static files.
Cloning 46 application files.
Deploying:
Uploading 12 files.
Uploaded 3 files.
Uploaded 6 files.
Uploaded 9 files.
Uploaded 12 files.
Initializing precompilation...
Sending batch containing 11 file(s) totaling 44KB.
Sending batch containing 1 blob(s) totaling 1KB.
Deploying new version.
Verifying availability:
Will check again in 1 seconds.
Will check again in 2 seconds.
Will check again in 4 seconds.
Closing update: new version is ready to start serving.
Updating datastore:
Uploading index definitions.
Deployment completed successfully
网址:http://mkyong-struts2gae.appspot.com/User/Login.action
Note
Finally, finished this long article. The overall integration is not much difficult, just need to fix Struts2 ognl security and TextBlock issues, hope Struts2’s team can fix this in future.
下载源代码
由于文件很大,所有 Struts2 jars 都被排除在外,需要手动下载。
Download – Struts2GoogleAppEngine.zip (23 KB)