2.1 Struts2概述
Struts2是以WebWork的设计思想为核心,吸收Struts1的部分优点后建立的一个兼容WebWork和Struts1的MVC框架。Struts2的目标是使Web开发变得更加容易。
2.1.1 Struts2起源背景
从2001年Struts框架诞生开始,作为MVC模式的第一个实现,Struts一直都是MVC领域中最流行的MVC框架,拥有广泛的市场支持。但随着Java EE项目复杂性的不断增高,Struts的缺陷也逐渐显露出来,大量的开发人员、软件公司开始选择更好的MVC解决方案,如JSF和Tapestry等。正是在这种背景下,Struts2框架诞生了。Struts2整合了两个优秀的MVC框架(Struts1和WebWork)的优点,从而保证了Struts2作为实际开发框架的成熟性。Struts2保留了Struts1的简单易用性,并且充分利用了WebWork的拦截器机制(AOP思想),是一个具有高度可扩展性的框架。
Struts2框架诞生后,取代了原有的Struts和WebWork框架,Struts2的开发团队也是由Struts和WebWork两个团队组成的,保证了技术体系的延续。而且WebWork不再推出新的版本,原来使用Struts和WebWork的开发人员都将转入使用Struts2框架。基于这种背景,Struts2在短时间内迅速成为MVC领域最流行的框架。
2.1.2 Struts2框架结构
Struts2中大量使用拦截器来处理用户请求,从而允许用户的业务逻辑控制器与Servlet API分离。如图2-1所示,用户请求提交给Struts2的核心控制器FilterDispatcher,FilterDispatcher根据请求调用相应的Action的execute()方法,并根据处理结果显示相应的JSP页面。其中,针对一些通用的功能,Struts2框架内置了许多拦截器,这些拦截器组成一个拦截器链,拦截器链会自动对请求应用这些通用性的功能。
图2-1 Struts2框架结构
注意 有关拦截器的种类以及配置等详细信息参见实践 2 的知识拓展。
2.1.3 Struts2控制器组件
Struts2的控制器组件是整个框架的核心,实际上,所有MVC框架都是以控制器组件为核心的。Struts2的控制器由两部分组成:FilterDispatcher和业务控制器Action。
1. FilterDispatcher
FilterDispatcher是一个Servlet过滤器,它是Struts2的核心组件,作用于整个Web应用程序,需要在web.xml中进行配置。
在web.xml中配置FilterDispatcher的代码如下所示。
<filter> <!-- 配置Struts2框架的核心Filter --> <filter-name>struts2</filter-name> <filter-class> <!-- 配置Struts2核心Filter的实现类 --> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
上述配置文件配置了FilterDispatcher过滤器,该过滤器对所有请求都进行过滤处理。
任何需要与Web应用整合的MVC框架都需要借助web.xml配置文件。通常MVC框架都需要在Web应用中加载一个核心控制器,对于Struts2框架而言,就是加载FilterDispatcher组件。只要Web应用加载了FilterDispatcher,FilterDispatcher就会加载并应用Struts2框架。因为FilterDispatcher是过滤器,故让Web应用加载FilterDispatcher时只需要在web.xml中使用<filter>及<filter-mapping>元素配置FilterDispatcher即可。
2. Action
Action是Struts2的业务控制器,如代码2-1所示是一个Struts2的Action示例。
【代码2-1】LoginAction.java
public class LoginAction { // 用户名 private String userName; // 密码 private String password; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } /** * 控制业务流程转向 * 返回一个字符串,可映射到任何视图或Action */ public String execute() { System.out.println("姓名为:" + userName); // 判断用户名为“haier”且密码为“soft”,则返回success,否则返回error if ("haier".equals(userName) && "soft".equals(password)) { return "success"; } return "error"; } }
通过上述代码可以发现Action无须实现任何接口,也无须继承任何Struts2的基类,该Action类完全是一个POJO,具有很高的可重用性。
Struts2中的Action类有如下优势:
Action类完全是一个POJO,具有良好的代码重用性;
Action类无须与Servlet API耦合,因此无论是应用还是测试都非常简单;
Action类的execute()方法仅返回一个字符串作为处理结果,该处理结果可映射到任何的视图或另一个Action。
注意 实际上,Struts2应用中起作用的业务控制器不是用户定义的Action,而是系统生成的Action代理类,该Action代理类以用户定义的Action为代理目标。
2.1.4 Struts2的配置文件
Struts2创建系统的Action代理时,需要使用Struts2的配置文件,在此文件中需要对用户定义的Action进行相关信息的配置。
Struts2的配置文件有两种:
配置Action的struts.xml文件;
配置Struts2全局属性的struts.properties文件。
1. struts.xml
在struts.xml文件中需要配置系统用到的Action。在配置Action时,需要指定该Action的实现类,并指定该Action处理结果与视图资源之间的映射关系。
如代码2-2所示是struts.xml配置文件的示例。
【代码2-2】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> <!-- 指定Struts2处于开发阶段,可以进行调试 --> <constant name="struts.devMode" value="true" /> <!-- Struts2的Action都必须配置在package里 --> <package name="p1" extends="struts-default" namespace="/admin"> <!-- 定义一个login的Action,实现类为com.haiersoft.LoginAction --> <action name="login" class="com.haiersoft.LoginAction"> <!-- 配置execute()方法返回值所对应的页面 --> <result name="error">/error.jsp</result> <!-- 如果result标签不配置name属性,其默认为success --> <result>/success.jsp</result> </action> </package> </struts>
在上述struts.xml文件中,声明了一个Action,并指定了Action的实现类,同时定义了多个result元素来指定execute()方法的返回值和视图资源之间的映射关系。例如:
<result name="error">/error.jsp</result>
表示当execute()方法的返回值是“error”字符串时,跳转到网站根目录下的error.jsp页面。
2. struts.properties
在struts.properties文件中可以配置Struts2的全局属性,如代码2-3所示。
【代码2-3】struts.properties
#指定Web应用的默认的编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 struts.i18n.encoding=GBK #当struts.xml修改后是否从新加载该文件,在开发阶段最好打开 struts.configuration.xml.reload=true #设置浏览器是否缓存静态内容,开发阶段最好关闭 struts.serve.static.browserCache=false
上述struts.properties文件中以key-value键值对的形式指定了Struts2应用的全局属性。
2.1.5 Struts2的标签库
Struts2的标签库也是Struts2框架的重要组成部分,提供了非常丰富的功能,这些标签不仅提供了表示层数据处理,而且提供了基本的流程控制功能,还提供了国际化、Ajax支持等功能。通过使用Struts2的标签,开发者可以最大限度地减少页面代码的编写。有关Struts2标签库的详细内容请参见本书第4章。
2.1.6 Struts2的处理步骤
Struts2框架对Web请求处理的具体步骤如下所述。
01 客户端浏览器发送一个请求,例如:/mypage.action。
02 这个请求经过核心控制器FilterDispatcher过滤处理,FilterDispatcher将请求转交给相应的Action代理。
03 Action代理通过配置文件中的信息找到对应的Action类,创建Action对象并调用其execute()方法。
04 在调用Action的过程前后,涉及相关拦截器的调用。拦截器链自动对请求应用通用功能,例如,自动化工作流、验证或文件上传等功能。
05 一旦Action执行完毕,Action代理根据struts.xml中的配置信息找到execute()方法返回值对应的结果。返回结果通常是视图资源(如JSP页面)或另一个Action。