本文主要介绍在 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,具体如下: 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。 创建 , 配置 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” 在 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 以及表单字段的 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 是如何处理的: 在调用该方法前,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 配置进行校验。下面代码片段是本示例中配置的校验参数,它指定了对哪些表单字段做哪些校验: Struts 2 定义了一些默认类型,例如 ,email, 可以校验 email 格式,在上例中 user.email 指定了校验表单的 email 字段,type=”requiredstring”表明该字段是必须的,type=”email”表明要检验 email 格式。所有的错误信息可以通过 key 来国际化。
另一种是通过编程校验,在 UserAction 中有一个方法: 注意该方法的命名,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 中加入了这样的配置信息: 该配置表示在当前 package 下的所有 action, 一旦有 java.lang.Exception 抛出,并且没有被相应 action 捕获的话,系统将显示错误页面,error.jsp
另外,struts 2 也支持在某个 action 内部定义异常处理,例如: 在错误页面中可以通过 <s2:property value="%{exception.message}" /> 显示异常信息。
总结
通过该示例开发,我们对 Struts 2 开发平台以及 Struts 2 框架有了一个基本认识,不过要熟练应用 Struts 2,还需要了解它的各类标签,OGNL 表达式。另外 Struts 2 还提供了一些高级特性,如 Interceptor 机制,IOC 机制。充分利用这些新特性会帮助我们更快,更方便地实现一些 Web 应用。
引言
作为 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,具体如下: 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。 创建 , 配置 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” 在 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 以及表单字段的 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 是如何处理的: 在调用该方法前,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 配置进行校验。下面代码片段是本示例中配置的校验参数,它指定了对哪些表单字段做哪些校验: Struts 2 定义了一些默认类型,例如 ,email, 可以校验 email 格式,在上例中 user.email 指定了校验表单的 email 字段,type=”requiredstring”表明该字段是必须的,type=”email”表明要检验 email 格式。所有的错误信息可以通过 key 来国际化。
另一种是通过编程校验,在 UserAction 中有一个方法: 注意该方法的命名,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 中加入了这样的配置信息: 该配置表示在当前 package 下的所有 action, 一旦有 java.lang.Exception 抛出,并且没有被相应 action 捕获的话,系统将显示错误页面,error.jsp
另外,struts 2 也支持在某个 action 内部定义异常处理,例如: 在错误页面中可以通过 <s2:property value="%{exception.message}" /> 显示异常信息。
总结
通过该示例开发,我们对 Struts 2 开发平台以及 Struts 2 框架有了一个基本认识,不过要熟练应用 Struts 2,还需要了解它的各类标签,OGNL 表达式。另外 Struts 2 还提供了一些高级特性,如 Interceptor 机制,IOC 机制。充分利用这些新特性会帮助我们更快,更方便地实现一些 Web 应用。