2008 年2 月28 日
Struts 2 是MVC 框架发展的最新阶段。Struts 2 从WebWork发展而来,而不是由Struts 1 演化而来,因此利用Struts 2 开发和部署应用程序有很多不同于Struts 1 的地方,尤其是在开发和部署Porlet方面,Struts 2 更是有着以往Portlet应用程序开发方式所无法比拟的优势。本文的目的就是通过在IBM 的WebSphere Portal Server 上开发和部署一个基于Struts 2 的Porlet应用,向读者介绍利用Struts 2 进行Portlet应用开发的优势和关键流程。
概述
WebSphere Portal Server5.1 及以上版本支持两种Portlet API:第一种是IBM Portlet,这种Portlet API 是WebSphere Portal Server 专有的一种Portlet API;第二种是符合JSR168 标准的Portlet API。由于JSR168 是一个开放的标准,因此符合JSR168 标准的Portlet将更易于移植。
IBM 为IBM Portlet API 和JSR168API 分别实现了基于Struts1 的Portlet开发框架,由于基于Struts1,这两种Portlet框架API 同Portlet API 耦合紧密,尤其需要指出的是由于无论IBM Portlet 还是在WebSphere Portal Server 上实现的JSR168 标准的Porlet API, 它们的接口都直接依赖于PortletRequest/PortletResponse对象,这就使得程序移植和单元测试等变得比较困难。此外,我们在使用Struts1 开发Servlet 应用时,习惯于将数据存放在request 作用域中,通过页面的跳转将数据呈现到jsp视图页面。但是,这种做法在portlet开发中是不可行的。与servlet 的生命周期有所不同,portlet存在操作响应阶段和呈现阶段。在portlet操作响应阶段存放在request 作用域的变量,在呈现阶段就会失效。在原有API 上解决这个问题既费时又不优雅,而Struts 2 对Portlet的支持将能够很好的解决这些问题。
本文就是要通过一个简单的示例应用程序的开发和部署过程,来展示Struts 2 怎样解决旧有的Portlet API 所无法克服的困难的。
本文的重点不在于开发一个Struts2 Web 应用程序,而在于开发一个作为Portlet的Struts2 应用程序所需的的实现和配置。读者可以了解到如何利用Struts 2 来创建一个Portlet,这个Portlet将完全独立于其所开发和部署的平台。
在示例应用程序的开发和部署中用到了下列产品:
?IBM WebSphere Portal Server 集成测试环境5.1
?IBM WebSphere Application Server Version 5.1
?Struts 2 Full Distribution 2.0.11
?IBM Rational Application developer 7(RAD7)
Porlet示例程序设计概述
示例应用程序是一个简单的用户登录程序。合法的用户将跳转到的登录成功页面,登录失败的用户则跳转到登录失败页面,并被要求输入正确的用户名和密码。用户可以自由的在Portlet的View、Edit 和Help 模式之间进行切换。应用程序视图部分分为以下几部分:
?登录页面(login.jsp)——提示用户输入正确的用户名和密码,登录应用程序。
?登录成功页面(success.jsp)——提示用户登录成功。
?登录失败页面(fail.jsp)——提示用户登录失败,提示用户输入正确的用户名和密码。
?Edit 页面(edit.jsp)——用户进入Edit 模式后的页面。
?Help 页面(help.jsp)——用户进入Help 模式后的页面。
?程序主类——Login.java。
图 1. 程序初始页面
下图是本文示例的Action 与页面的交互图:图 2. Action 与页面的交互图
利用Struts2 实现Portlet
在本文中,使用Struts2 开发Portlet应用需要经历以下步骤:
1.使用RAD7 建立开发环境
2.生成web.xml 配置文件
3.生成portlet.xml 配置文件
4.编辑jsp 文件
5.应用Struts2
6.部署Portlet 应用程序
7.访问Portlet 应用
使用RAD7 建立开发环境
在Rational Application developer 7 中启动一个Portlet项目,需要遵循下列步骤:
1.选择新建一个Portlet项目,如图3 所示:
图 3. 新建一个Portlet项目
2.输入项目名Struts2TestPortlet,目标运行时选择WebSphere Portal v5.1 或者更高版本,
注意Portlet API 选择JSR 168 Portlet, 注意勾掉创建portlet选项,点击完成按钮。如图4 所示:
图 4. 设置项目属性
生成portlet项目及其结构如图5 所示:图 5.portlet 项目及其结构
3.接下来到Apache 官方网站下载strtus2 的完整版(Full Distribution)。将下载到的Zip 文
件解压缩。本文中使用的版本为struts-2.0.11。将struts-2.0.11 j4 文件夹下的
backport-util-concurrent-3.0.jar,retrotranslator-runtime-1.2.2.jar,
struts2-core-j4-2.0.11.jar,xwork-j4-2.0.4.jar 和lib 目录下的ognl-2.6.11.jar,
freemarker-2.3.8.jar 文件拷贝到portlet web 工程的WEB-INF/lib 目录下。
在这里需要注意的是从j4 文件夹下拷贝过来的JAR 包,这是因为WebSphere Portal Sever
5.1 基于jdk1.4,而j4 文件夹下的内容就是Struts2 支持JDK1.4 的JAR 文件。
生成web.xml 配置文件
双击WEB-INF/web.xml,打开web 部署描述符界面,如图6 所示:
图 6.web 部署描述符界面
切换到过滤器选项卡,点击添加按钮,创建一个过滤器,名称设定为Struts2 Filter, URL 映射为/*,并且使用现有的过滤器类org.apache.struts2.dispatcher.FilterDispatcher,如图7 所示。点击完成
图7. 创建一个过滤器
生成的web.xml 描述文件内容如下所示:
web.xml 描述文件内容
"https://www.doczj.com/doc/f315805348.html,/dtd/web-app_2_3.dtd">
org.apache.struts2.dispatcher.FilterDispatcher
生成portlet.xml 配置文件
双击portlet.xml,打开Portlet部署描述符界面,切换到portlet选项卡,如图8 所示:图8.Portlet 部署描述符界面
点击添加按钮,添加一个portlet,输入portlet类型
org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher,确定,如图9 所示:
图9. 添加portlet
编辑该portlet的其它信息,分别设定Portlet名称,显示名称,标题,简短标题,关键字。本示例中均输入Struts2 Test Portlet。如图10 所示:
图10. 编辑portlet信息
接下来在本页中编辑受支持的方式text/html, 添加portlet模式view,edit, help。如图11 所示:图11. 添加portlet模式
Portlet模式让Portlet决定它该显示什么内容和执行什么动作。调用一个Portlet的时候,Portlet容器会提供一个Portlet模式给那个Portlet。当在处理一个请求动作时,Portlet的模式是可以用程序来改变的。
JSR168 规范定义了三个Portlet模式:浏览(View)、编辑(Edit) 和帮助(Help)。Struts2 支持其中的全部三个模式。同时Portal 还可以根据使用者的角色,来决定是要提供( 显示) 哪几个Portlet模式给使用者操作。在我们的例子中就使用了这三个模式。
继续在本页中添加初始化参数,首先是Namespace 相关的参数见表1:
表 1. Namespace 相关的参数
考虑到在同一个Web 应用中需要同名Action,Struts2 以命名空间方式管理Action。同一个命名空间里不能有同名的Action,不同的命名空间里可以有同名的Action。Struts2 不支持为单独的Action 设置命名空间,而是通过为包指定namespace 属性来为下面所有的Action 指定共同的命名空间。这一点可以从下面的portlet.xml 清单中看出。Struts2 对portlet的三种模式的支持是通过namespace 体现的。View,Edit,Help 三种模式分别对应ViewNamespace, editNamespace, helpNamespace。Action 相关的参数见表2:
表 2. Action 相关的参数
这些参数指定了在portlet的三种模式下的默认aciton名称,进入View、Edit、Help 模式分别首先调用名称为view、edit、help 的action。
图12. 编辑portlet初始化参数
生成portlet.xml 文件如下:
portlet.xml 描述文件内容
xmlns="https://www.doczj.com/doc/f315805348.html,/xml/ns/portlet/portlet-app_1_0.xsd"
version="1.0" xmlns:xsi="https://www.doczj.com/doc/f315805348.html,/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.doczj.com/doc/f315805348.html,/xml/ns/portlet/portlet-app_1_0.x sd
https://www.doczj.com/doc/f315805348.html,/xml/ns/portlet/portlet-app_1_0.xsd"
id="com.ibm.faces.portlet.FacesPortlet.3ccbdcb861">
org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher
在本清单中Portlet类“org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher”在将Struts2 集成到Portlet中起到了关键作用,该类将Portlet操作分发给Struts2。
编辑jsp文件
在WEB-INF 下新建jsp文件夹,并生成几个jsp文件及内容如下:
success.jsp
edit.jsp
help.jsp
应用Struts2
建立Struts2 配置文件struts.xml
在src目录下建立struts.xml,工程构建之后struts.xml 会被置于WEB-INF/classes 下,这也是Struts2 默认的配置文件路径。
struts.xml 文件是基于Struts2 的项目的核心配置文件。在portlet开发过程最重要的内容就是要将"struts-portlet-default.xml" 包含进来,这个xml 文件存在于前面步骤中我们拷贝过来的
struts2-core-j4-2.0.11.jar 中,只有把它包含进来我们才能使Struts2 支持portlet。接下来描述的内容就是将前面定义的action 和页面关联起来。从中可以看出我们定义的login 这个actoin的输入界面是input.jsp,如果成功则会被转向success.jsp,失败则会被转向fail.jsp。
struts.xml
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"https://www.doczj.com/doc/f315805348.html,/dtds/struts-2.0.dtd">
namespace="/view"> name="success">/WEB-INF/jsp/success.jsp
namespace="/edit">
namespace="/help">
新建java 类Login.java
Login.java
package struts2TestPortlet.action;
public class Login extends ActionSupport {
String username;
String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
https://www.doczj.com/doc/f315805348.html,ername = username;
}
public String execute() throws Exception {
同Struts1 的比较
在实现相同功能的前提下,我们不妨看一下Struts 1 的相关实现,示例中采用的是IBM 的Struts for JSR168 Portlet实现。
首先,我们必须针对用户输入的表单数据创建一个ActionForm,当然,您也可以通过xml 文件配置的方式创建一个DynamicForm。
java 类LoginActionForm.java
public class LoginActionForm extends ActionForm {
String username;
String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
https://www.doczj.com/doc/f315805348.html,ername = username;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
username = null;
password = null;
接下来,我们需要实现一个Action 类。
java 类LoginAction.java
public class LoginAction extends com.ibm.portal.struts.action.StrutsAction { public ActionForward execute(ActionMapping mapping, ActionForm form,
PortletRequest request, PortletResponse response) throws Exception {
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
LoginActionFormloginActionForm = (LoginActionForm) form;
String username = loginActionForm.getUsername();
String password = loginActionForm.getPassword();
if (username.equals("yanzhid") &&password.equals("pwd")) {
StrutsViewCommand.addAttributeNameToSave("username");
request.setAttribute("username", username);
return mapping.findForward("success");
} else {
return mapping.findForward("fail");
}
}
}
在Struts1 中,我们习惯使用JSTL 从request 作用域中取得数据,呈现到JSP 页面上,success.jsp 页面被改动如下:
由于精通Struts1 的读者很多,其余相关改动和struts1 的配置我们不再拗述,请读者查阅相关文献。从中我们可以看出struts2 和struts1 的区别,并从中体会到Struts2 的优势:
1.捕获输入:
Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他
JavaBean 不能用作ActionForm,开发者经常创建多余的类捕获输入。当然您也可以使用xml 文件描述一个DynamicForm,但工作量并未显著减少。
Struts 2 可以直接使用Action 属性作为输入属性,消除了对第二个输入对象的需求。当然,
Struts2 也支持ActionForm模式,用作输入/ 输出对象。
2.Action 类:
Struts1 要求Action 类继承一个抽象基类。Struts1 的一个普遍问题是使用抽象类编程而不是接口。
Struts2 Action 类可以实现一个Action 接口,也可实现其他接口。Struts2 提供一个
ActionSupport基类去实现常用的接口,但Action 接口不是必须的,任何有execute 标识的POJO 对象都可以用作Struts2 的Action 对象。
3.Portlet依赖:
Struts1 Action 依赖于Portlet API , 当一个Action 被调用时,PorletRequest和
PortletResponse被传递给execute 方法。
Struts2 Action 不依赖于容器,允许Action 脱离容器单独被测试。如果需要,Struts2 Action 仍然可以访问初始的request 和response。但是,其他的元素减少或者消除了直接访问
PorletRequest和PortletResponse的必要性。
4.可测性:
测试Struts1 Action 的一个主要问题是execute 方法暴露了Portlet API,这使得测试要依
赖于容器。
Struts2 Action 可以通过初始化、设置属性、调用方法来测试,使测试更容易。
5.对Portlet的支持程度:
Struts1 框架天生并不支持Portlet, 为了将大批Struts 程序员吸引到WebSphere Portal 开发上来,IBM 公司针对自己的两种Portlet实现(IBM Portlet和JSR168 Portlet), 分别对
Struts 框架进行了扩展,以适应Portlet开发。细心的读者一定已经发现了,我们的LoginAction 类继承的是com.ibm.portal.struts.action.StrutsAction这个基类,而不是Struts1 官方框架中的Action 类。
Struts1 程序员刚刚进行Portlet开发的时候,一般会忽略一个重要的问题。与servlet 的生命周期有所不同,portlet存在操作响应(Action) 阶段和呈现(Render)阶段。在portlet操作响应阶段存放在request 作用域的数据,在呈现阶段就会失效。为了解决这个问题,一个方案
就是把数据放在session 作用域中,考虑到服务器性能的原因,这个方案显然不被推荐。另一
个方案就是使用IBM 提供的一些特殊的API, 按照LoginAction那样,在将数据放在request 作用域之前,将数据变量名作为参数传给StrutsViewCommand的
addAttributeNameToSave方法。为了说明这个问题,我们可以将
StrutsViewCommand.addAttributeNameToSave("username") 这行代码删掉,程序运行候就可以发现,success.jsp将不会呈现username 变量中保存的数据。
Struts2 的官方框架支持JSR168 Portlet, 除了前期需要对web.xml、portlet.xml 和
struts.xml 文件进行少许特殊配置外,程序员不需要考虑Portlet和Servlet 之间的不同,无论是Action 类的开发还是JSP 页面中Struts2 标签的应用,同在Servlet 容器中用法是完全一样的。
Struts2 的验证功能
采用Struts2 的校验框架时,只需为该Action 指定一个校验文件即可。该文件指定了Action 的属性必须满足怎样的规则,下面清单即本应用中Action 的校验文件的代码。Struts2 的校验文件规则与Struts1 的校验文件设计方式不同,Struts2 中每个Action 都可以有一个校验文件,该文件的文件名遵守如下规则:
前面的Action 名是可以改变的,后面的-validation.xml 部分是固定不变的,且该文件应该被保存于Action class 文件相同的路径下。如在本例中此校验文件在项目构建后保存在
WEB-INF/classes/Struts2TestPortlet/action/ 下,与login.class在同一目录中。
Login-validation.xml
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"https://www.doczj.com/doc/f315805348.html,/xwork/xwork-validator-1.0.2.dtd">
true
true
部署Portlet应用程序
首先在RAD7 控制台的服务器视图中添加一个可以运行Portlet的服务器。该视图中单击鼠标右键,选择新建—>服务器。如图13 所示:
图13. 新建服务器
在弹出的新建服务器窗口中选择目标运行服务器,在本例中我们选择WebSphere Portal V5.1 测试环境, 对话框底部的服务器运行时呈现为WebSphere Portal V5.1。在服务器主机名中输入localhost,如图14 所示。点击下一步,默认端口号为9081。
图14. 选择目标运行服务器
2012年第11卷第6期 产业与科技论坛2012.(11).6 Industrial &Science Tribune Struts2框架工作原理及应用体会 □宋 君 张家爱 【摘要】通过针对特定用户的分析,搭建以Struts2为技术核心的旅行社管理系统。本文简单的介绍了MVC 、 Struts2的工作原理,同时总结了在项目制作过程中所得到的心得。 【关键词】 Struts2;MVC ;FilterDispatcher ;Action 【基金项目】本文为大学生科技创新院级基金项目(编号:2011070)成果 【作者单位】宋君,吉林农业科技学院信息工程学院;张家爱,吉林农业科技学院信息工程学院教师 本着锻炼自我与积极参与到实用性技术的目标,以发掘自身创新意识为前提。利用空闲时间,在老师的指导下,进行了一次大学生创新项目的实践性活动。本着实用原则,以某中小旅行社为客户(根据用户需求,匿名),以Struts2框架为基点,进行了一次旅行社管理系统的开发。在项目结束之余, 特将在项目过程中经历的种种认识进行了简单的总结,希望让阅读本文的朋友们,更多的参与到此类活动中。 一、基础思想— ——MVC 简述作为时下经典框架之一, MVC 具有其独特的价值。MVC 框架简单的说,就是将数据模型与用户视图进行分离。通过控制器进行协调处理的一种结构是框架。同时,也是本文中要讨论的Sturts2框架的基础思想。 M 是指模型层(Model ),V 是指用户视图(View ),C 则是指控制器 (Controller )。这种划分方式是以将模型层与视图层进行代码分离,从而降低两者之间的耦合性,使同一程序可以使用不同形式进行表现。不同层之间的修改不会或尽量少的印象到其他层功能的史前为前提。有效的提高的代码的维护性和设计难度。 图1 二、 Struts2工作原理(一)Struts2框架组成。Struts2框架由三个主要部分组成:核心控制器、业务控制器,以及由用户实现的业务逻辑组件。这里我们将侧重于核心控制器与业务控制器的理解与说明。 (二)核心控制器:FilterDispatcher 。FilterDispatcher 是Struts2框架的核心控制器,在此,我们可以将FilterDispatcher 看作一个类似于过滤网的过滤器。当用户发出请求,并到达Web 硬哟那种时,该过滤器会过滤用户请求。如果用户请求的结尾为action ,则将该请求转入Struts2框架进行处理。当Struts2框架获得了*.actio 请求后,会根据请求前面“*”的那部分内容,决定调用哪个业务逻辑组件作为响应单位。这里需要说明的是Struts2用来处理用户请求的Action 实例并不是业务控制器,而是作为Action 的代理———正因为Struts2的一大特点,与Servlet API 的非耦合性,使得用户实现的业务控制器无法直接处理用户请求。有效的提高了后期调试维护的效率。而Struts2框架再次提供了了一系列的拦截器。这些拦截器负责将HttpServletRequest 请求的参数解析出来,传入Action 中,并毁掉Action 的Execute 方法来处理用户请求。用户实现的Action 类仅作为Struts2的Action 代理的代理目标。用户实现的业务控制器则包含了对用户请求的处理。用户的请求数据包含在HttpServletRequest 对象中,而用户的Action 类无需访问HttpServletRequest 对象。拦截器负责将HttpServletRequest 里的请求数据解析出来,并传给业务逻辑组件Action 实例。 (三)业务控制器。业务控制器就是前文提到的用来实现用户Action 的实力,这里的每个Action 类通常包含有一个execute 方法,当业务控制器处理完用户的请求后,该方法将会针对此次处理返回一个字符串— ——该字符串就是一个逻辑树图名。当程序开发人员开发出系统所需要的业务控制器后,还需要针对性的配置Struts2的Action ,即需要配置Ac- tion 的以下三个部分:(1)Action 所处理的URl 。(2)Action 组件所对应的实现类。(3)Action 里包含的逻辑试图和物理资源之间的对应关系。每个Action 都要处理一个用户请求,而用户请求则总是包含有指定的URL 。当核心控制器过滤用户请求,并调用后,根据请求的URL 和Action 处理URL 之间的对应关系来处理转发。 · 342·
Struts 2作业 1.简述什么是MVC? 答:MVC 的全称为model-view-controller(模型-视图-控制器)。MVC 是一种开发应用程序的模式,这个模式已经具有了很好的框架架构,并且十分容易维护。使用MVC 开发出来的应用程序一般包括以下几块内容:·控制器(Controller):控制器类处理客户端向Web 应用程序发出的请求,获取数据,并指定返回给客户端,用来显示处理结果的视图。·模型(Model):模型类代表了应用程序的数据,这些数据通常具有一个数据验证逻辑,用来使得这些数据必须符合业务逻辑。·视图(View):视图类是Web 应用程序中用来生成并显示HTML 格式的服务器端对客户端请求的响应结果的模板文件 2.Struts 2以(WebWork)为核心,采用(拦截器)的机制来处理用户的 请求。 3.简述一个请求在Struts 2框架中的处理流程,请按自己对框架的理解叙述。答:1-用户提交自己的请求;2-由web.xml拦截,转发到action进行处理;3- Struts.xml根据相应的action配置,调用相应的方法来处理,并根据结果转发到不同的页面。 4.不属于Action接口中定义的字符串常量是( B )? A)SUCCESS B)FAILURE C)ERROR D)INPUT 5.资源文件的后缀名为(D)? A)txt B)doc C)property D)properties 6.在JSP页面中可以通过Struts 2提供的(D)标签来输出国际化信息。 A)
第一章Struts2的起源和发展 说到网络应用很难让人不联想到网络信息的浏览,自从Internet进入民用领域之后,上网成为了越来越多的人闲暇时光的消磨手法。于是网络系统的开发也变得越来越总要。 1.1 Web技术的发展 随着Internet技术的大面积应用和发展,传统的静态HTML页面由于缺乏足够的用户交互能力已经无法满足日益膨胀的网络需求。人们希望Web应用中能够包含更多的动态交互功能,于是为了应对拥有更广泛用户群的动态Web开发,软件开发商分别推出的ASP和JSP两款动态网站开发解决方案。但是当时的JSP 开发并没有很科学的层次设计,最初的JSP开发中逻辑代码和前端代码杂合在一起。虽然在最初开发时这样的做法使得开发非常的容易,然而随着Web系统的使用越来越广泛,应用规模的日益增长,如果继续使用传统的简单的JSP + Servlet 结构进行Web系统的开发,则会由于系统层次混乱而导致系统的开发难度和维护成本越来越大,最终使开发过程陷入困境。 1.2 MVC思想进入Web系统开发 面对开发过程中所出现的困难,开发者们试图寻找一种能够使得开发结构更加具有条理性的开发模式。根据以往面向对象系统设计的经验,开发者开始将MVC开发模式引入Web系统的开发。MVC模式将一个应用分为三个基本部分:Model(模型)、View(视图)、Controller(控制器)。在此模式中触发事件由控制器捕获,并根据事件的类型来改变模型和视图。这样既可将系统模型与视图分离,从而使各部分能够工作在最小的耦合状态下协同工作,从来提高系统的扩展性和可维护性。将其引入Web系统开发后,系统模式由传统的JSP完成用户请求和响应改变为由控制器捕获用户请求,JavaBean完成模型操作,而JSP专门负责响应用户需求。老一代的开发框架Struts1便是这时的产物。
Struts2中数据标签使用示例 S truts2提供了大量丰富的标签供使用,它不再像S truts1中一样,将种类标签进行分门列别,但可以根据其使用的用途用以区别。本文通过对S truts2中数据标签的学习,来对S truts2中标签的学习起到一个抛砖引玉的作用。 文中将介绍Action标签、Bean标签、Data标签、Include标签、P aram标签、Set标签、T ext标签、P roperty 标签等标签。 代码下载:https://www.doczj.com/doc/f315805348.html,/y1ps2Mjpc3NiLKuetMOpCsZOOypD6KSdo8-46Zy2wpoMcABeo4vOC NJXtWDEO93-TXgZogwAF YxSOni5BEG2EoN65OFwHdG71v-/St ruts2DataTags.rar?download 一、