Java EE轻量级解决方案:S2SH
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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。