基于Struts 2开发Web应用

来源:互联网 发布:蚁群算法改进 编辑:程序博客网 时间:2024/05/01 14:48
本文主要介绍在 IBM 产品平台上开发基于 Struts 2 的 Web 应用。Struts 2 与传统的 Struts 1 已经有了本质区别,例如在 Struts 2 中不再需要 ActionForm,任何 Java Bean 都可以用来捕获 form 表单输入参数等。本文将首先介绍如何利用 Rational Software Architect 7(RSA 7)以及 WebSphere Application Server 6.1(WAS 6.1)搭建 Struts 2 开发环境,然后通过一个实例介绍如何开发 Struts 2 应用。

引言

作为 Java Web 应用的典型框架,Struts 一直受到 Java 开发者的青睐,Struts 2 作为 Struts 发展的又一个里程碑,以 WebWork 为基础,提供了更易于使用,功能更强的 MVC 框架。同时它可以帮助开发人员更快速、高效、方便地实现一个 Java Web 应用系统。

对于开发人员来讲,不同的项目可能需要不同的开发和运行 Struts 2 的平台,Struts 2 需要以下环境:Servlet API 2.4, JSP API 2.0, Java 5。IBM WebSphere Application Server 6.1(以下简称 WAS 6.1) 符合 Sturts 2 对运行环境的所有要求。另外,IBM Rational Software Architect 7(以下简称 RSA)提供了设计、开发各种应用的工具,其中包括创建和开发 Web 应用。二者的组合将是开发 Struts 2 的理想平台。

基于 RSA 及 WAS 搭建 Struts 2 开发平台

首先我们使用 RSA 创建一个动态 Web 项目,我们假设 RSA 中已经创建了一个 WAS 6.1 的服务器:

图 1. 在 RSA 中创建 WAS 6.1 运行环境


在创建该项目的过程中,需要注意正确设置“目标运行时服务器”以及“动态 Web 模块 版本“, 如下图:

图 2. 设置动态 Web 项目


其他按默认配置,点击”完成”。创建完项目后,项目的基本包结构会自动生成,为了使该 Web 项目使用 Struts 2 框架,我们需要做一下配置:

配置 Struts 2 类库

本示例使用 Struts 2.1.6 版本 , 所使用的类库可以从 http://apache.etoak.com/struts/library/struts-2.1.6-lib.zip下载,如下图,拷贝相应 jar 包到 Sample/WebContent/WEB-INF/lib 下。注意,本示例只拷贝了一些基本 jar 包,对于需要使用到 Struts 2 复杂功能的应用,需要另外拷贝相应 jar 包。

图 3. 设置 Struts 2 依赖的 Jar 包


配置 web.xml

为了让所有 web 请求通过 struts 2 框架处理,我们需要在 web.xml 中设置相应的 filter 以及 filter mapping, 对于 struts 2.1.6, 应设置成如下图高亮部分:

图 4. 在 web.xml 中设置 filter 和 filter mapping


对于 Struts 2 早期版本(2.1.3 之前),一般设置 filter 为 FilterDispatcher,具体如下:
  1. <filter> 
  2.     <filter-name>struts2</filter-name>                 
  3.     <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> 
  4. </filter> 
  5. <filter-mapping> 
  6.     <filter-name>struts2</filter-name> 
  7.     <url-pattern>/*</url-pattern> 
  8. </filter-mapping>
复制代码
Stuts 2 的 taglib 已经自动包含在 struts-core.jar, 服务器会自动找到相应 taglib,所以 web.xml 中不再需要设置 taglib。

配置 Web 容器

当在 WAS 6.1 上运行 struts 2 应用程序时,需要另外设置 web 容器的一个定制属性:

com.ibm.ws.webcontainer.invokefilterscompatibility=true, 否则,所有 Struts 2 Action 不起作用。该设置可以在 WAS 控制台上设置如下:

图 5. 设置 Web 容器


以上步骤完成了开发 struts 2 应用的准备工作,下面我们开发一个示例。


示例开发

该示例包括两个页面,第一个是管理员浏览所有系统用户(userList.jsp),第二个是管理员创建一个新用户(user.jsp)。图 6 和图 7 分别是两个示例的应用截图。

图 6 . 浏览系统用户


图 7. 点击 “创建”按钮创建新用户


点击“提交”,如果通过校验,则返回到第一个页面,如果校验失败,仍回到当前页面,并提示错误信息。

下面我们开发该应用的各个组件:

创建 Action

创建基类

通过基类实现 SessionAware, ServletRequestAware, ServletResponseAware 接口,可以使用 IOC 方式初始化 session, request 和 response。这种实现可以方便所有子类访问 session, request 和 response。
  1. import java.util.Map;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;

  4. import org.apache.struts2.interceptor.ServletRequestAware;
  5. import org.apache.struts2.interceptor.ServletResponseAware;
  6. import org.apache.struts2.interceptor.SessionAware;

  7. import com.opensymphony.xwork2.ActionSupport;

  8. public class  BaseAction extends ActionSupport 
  9.         implements SessionAware, ServletRequestAware, ServletResponseAware{
  10.         
  11.         private Map sessionMap;
  12.         private HttpServletRequest request;
  13.     private HttpServletResponse response;
  14.     
  15.     public void setServletRequest(HttpServletRequest request) {
  16.         this.request = request;
  17.     }
  18.     
  19.     public void setServletResponse(HttpServletResponse response) {
  20.         this.response = response;
  21.     }
  22.     
  23.     public void setSession(Map map){
  24.             this.sessionMap=map;
  25.     }
  26.     
  27.     public HttpServletRequest getHttpServletRequest(){
  28.             return request;
  29.     }
  30.     
  31.     public HttpServletResponse getHttpServletResponse(){
  32.             return response;
  33.     }
  34.     
  35.     public Map getSession(){
  36.             return sessionMap;
  37.     }
  38. }
复制代码
创建 , 配置 Action

在该示例中,所有 form 表单提交使用一个 Action 类,该类的不同方法将作为不同表单提交的 Action。在该示例中,execute(), createOrEditUser(), submitUser(), deleteUser() 对应于不同表单对应的 action。

图 8. UserAction 代码


在 Struts 2 应用中,action 的配置文件应该位于类根路径下,一个 Struts 2 应用中可以存在多个 action 配置文件,但这些文件需要在 struts.xml 中引用,本例所有 action 在 struts-user.xml 中定义,struts.xml 引用 struts-user.xml。

在 struts-user.xml 中可以看到不同的类方法被配置成不同的 Action, 如果没有指定方法,那么 struts 2 框架会默认调用 execute(), 例如:”showUserList”
  1. <!DOCTYPE struts PUBLIC
  2.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
  3.     "http://struts.apache.org/dtds/struts-2.0.dtd">
  4. <struts>                
  5.     <package name="user" extends="struts-default" namespace="/admin">
  6.         ……………
  7.         <!-- user list -->
  8.                 <action name="showUserList" class="sample.action.UserAction">        
  9.                         <result>/WEB-INF/page/userList.jsp</result>                        
  10.                 </action>
  11.                 
  12.                 <!-- add user -->
  13.                 <action name="createOrEditUser" 
  14.                     class="sample.action.UserAction" 
  15.                         method="createOrEditUser">
  16.                         <result>/WEB-INF/page/user.jsp</result>
  17.                 </action>
  18.                 
  19.                 <action name="submitUser" 
  20.                     class="sample.action.UserAction" 
  21.                         method="submitUser">        
  22.                         <result name="input">/WEB-INF/page/user.jsp</result>
  23.                         <result name="userList" type="chain">showUserList</result>
  24.                 </action>                
  25.                 ……………                                        
  26.         </package>
  27. </struts>
复制代码
在 Struts 2 中,如果一个 Action 需要调用另一个 Action, 可以设置 result 的 type 为 chain, 如前面代码片段中的 <result name="userList"type="chain">showUserList</result>

开发页面

在开发 Struts 2 应用时,不可避免会使用大量的 Struts 2 标签,默认 Struts 2 解释这些标签生成 HTML 代码时会加上一些额外的代码,例如可能把 <tr><td> 自动加上,如果我们选择自己灵活控制代码格式,可以参考本示例在 struts.properties 里设置 struts.ui.theme=simple, struts.properties 同样位于类根路径下:

图 9.Struts 标签及配置文件


下面我们通过 user.jsp 来展示 Struts 2 框架是如何关联 Jsp, Action 以及表单字段的
  1. <%@ taglib prefix="s2" uri="/struts-tags"%>
  2. ........
  3. <s2:form action="submitUser" name="submitUser" namespace="/admin">
  4.         
  5.         <table>
  6.             <tr>
  7.                 <td><s2:text name="User.Name"/></td>
  8.                 <td><s2:textfield name="user.userName"/></td>
  9.             </tr>
  10.             <tr>
  11.                 <td><s2:text name="User.Password"/></td>
  12.                 <td><s2:password name="user.password"/></td>
  13.             </tr>
  14.             <tr>
  15.                 <td><s2:text name="User.Email"/></td>
  16.                 <td><s2:textfield name="user.email"/></td>
  17.             </tr>
  18.             ……………
  19.         </table>
  20. </s2:form>
复制代码
S2:form 标签的 action 属性指定了 form 要提交到的 action, 该 action 名已经在 struts-user.xml 中定义。Namespace 属性和 struts-user.xml 中保持了一致,根据 struts-user.xml 的配置信息,该 form 就会被提交到 UserAction 的 submitUser 方法,但是表单各个字段值是如何被 Action 识别的呢?这是由代表 HTML 各种控件的 Struts 2 标签 name 属性指定的,例如 <s2:textfield name="user.userName"/> 就将该字段的值直接映射到 UserAction 的 user 实例变量的 userName 属性,注意,这里要求 user 对象对应的 User 类必须有一个空的构造函数,另外这里的 user 应该是一个标准的 JavaBean, 所有属性应该有 get,set 方法。

我们看一下表单提交后,action 是如何处理的:
  1. public String submitUser() {
  2.     userService.addUser(user);
  3.     return "userList";
  4. }
复制代码
在调用该方法前,Struts 2 框架已经将所有表单参数自动组装到 user 对象中,所以该方法可以直接访问 user 对象,并对其做相应处理 , 该示例中的 userService 是负责 user 对象的增,删,改操作。

添加完 user 对象,该 action 返回了一个字符串”userList”, 该字符串是 struts-user.xml 中 submitUser action 设置的一个返回结果,该返回结果其实是调用另一个 action 来显示现有 user 列表。

表单校验

Struts 2 提供了很多种校验方式,一种是配置方式,可以用来校验基本数据信息,另一种是编程校验,可以用来校验较为复杂的业务逻辑。

如果是通过配置来校验,需要在 Action 类的同目录下建一个 xml 文件,命名规则是 action 类名 -action 别名 -validation.xml。例如,本示例中:UserAction-submitUser-validation.xml, 当 submitUser action 被调用的时候,会先通过该 xml 配置进行校验。下面代码片段是本示例中配置的校验参数,它指定了对哪些表单字段做哪些校验:
  1. <validators>
  2.         <field name="user.userName">
  3.                 <field-validator type="requiredstring">
  4.                         <param name="trim">true</param>                        
  5.                         <message key="User.UserName.Required"/>
  6.                 </field-validator>
  7.                 <field-validator type="stringlength">
  8.                     <param name="minLength">1</param>
  9.                     <param name="maxLength">20</param>
  10.                     <message key="User.UserName.Length"></message>
  11.            </field-validator>
  12.         </field>
  13.         
  14.         <field name="user.email">
  15.           <field-validator type="requiredstring">
  16.               <message key="User.Email.Required"></message>
  17.           </field-validator>
  18.           <field-validator type="email">
  19.               <message key="User.Email.Format"></message>
  20.           </field-validator>
  21.         </field>        
  22.         
  23. </validators>
复制代码
Struts 2 定义了一些默认类型,例如 ,email, 可以校验 email 格式,在上例中 user.email 指定了校验表单的 email 字段,type=”requiredstring”表明该字段是必须的,type=”email”表明要检验 email 格式。所有的错误信息可以通过 key 来国际化。

另一种是通过编程校验,在 UserAction 中有一个方法:
  1. public void validateSubmitUser(){
  2.     if (user.getPassword().length() < 6){
  3.         this.addFieldError("user.password", getText("User.Password.Length"));
  4.     }
  5.                 
  6. }
复制代码
注意该方法的命名,validate+Action 方法名,也就是说该方法会在调用 submitUser Action 时自动被 Struts 2 框架调用。

国际化

Struts 2 中提供了各种机制对日期格式,数字格式做相应的国际化。例如通过 Action 同目录下的 package.properties, 具体可以参照附件,示例代码。

对于普通文本的国际化,需要做以下步骤:

   1. 设置国际化加载文件路径

      struts.properties 中的 struts.custom.i18n.resources 设置了 struts 2 需要自动加载的国际化文件

   2. 访问国际化资源

      任何继承自 ActionSupport 的 Action 类都可以直接使用 getText 方法根据当前 locale 获取相应键的值

在 JSP 中可以使用 OGNL 表达式 %{getText('key')} 或者 <s2:text name="key"/> 来访问国际化资源。

最后,如果以上方式都不适用,可以使用 com.opensymphony.xwork2.util.LocalizedTextUtil 工具类来访问国际化资源。

异常处理

一般来说,web 应用都会设置一些统一错误页面,用来显示那些未被 try catch 捕捉到的异常信息,该示例在 struts-user.xml 中加入了这样的配置信息:
  1. <global-results>                        
  2.     <result name="Exception">/WEB-INF/page/error.jsp</result>                        
  3. </global-results>

  4. <global-exception-mappings>
  5. <exception-mapping exception="java.lang.Exception" result="Exception"/>
  6. </global-exception-mappings>
复制代码
该配置表示在当前 package 下的所有 action, 一旦有 java.lang.Exception 抛出,并且没有被相应 action 捕获的话,系统将显示错误页面,error.jsp

另外,struts 2 也支持在某个 action 内部定义异常处理,例如:
  1. <action name=”xxx” class=”xxx” method=”xxx”>
  2.     …….
  3.     <exception-mapping exception="java.lang.Exception" result="custom_error"/>
  4.     <result name="custom_error">/WEB-INF/page/common/error.jsp</result>
  5.     …….
  6. </action>
复制代码
在错误页面中可以通过 <s2:property value="%{exception.message}" /> 显示异常信息。

总结

通过该示例开发,我们对 Struts 2 开发平台以及 Struts 2 框架有了一个基本认识,不过要熟练应用 Struts 2,还需要了解它的各类标签,OGNL 表达式。另外 Struts 2 还提供了一些高级特性,如 Interceptor 机制,IOC 机制。充分利用这些新特性会帮助我们更快,更方便地实现一些 Web 应用。
原创粉丝点击