zoukankan      html  css  js  c++  java
  • Struts2框架学习第三章——Struts2基础

    本章要点

    —  Struts 1框架的基本知识

    — 使用Struts 1框架开发Web应用

    —  WebWork框架的基本知识

    — 使用WebWork框架开发Web应用

    — 在Eclipse中整合Tomcat

    — 使用Eclipse开发Web应用

    — 为Web应用增加Struts 2支持

    —  Struts 2框架的MVC组件

    —  Struts 2框架的流程

    — 通过web.xml文件加载Struts 2框架

    — 通过struts.properties文件配置Struts 2属性

    —  struts.xml文件的结构

    — 前面一章已经大致介绍了Struts 2应用的基本情况,通过前一章的学习,读者应该对Struts 2框架有了一个大致的掌握。但对于各知识点的细节,还需要进一步学习,本章将详细介绍Struts 2框架的基础部分。

    因为Struts 2是在WebWork和Struts 1的基础上发展起来的,因此掌握一定的WebWork和Struts 1框架的知识,将对于掌握Struts 2框架大有裨益。特别是WebWork方面的开发经验,绝大部分都可以适用于Struts 2应用的开发。本章将会简要介绍Struts 1和WebWork框架的使用。

    本章还将介绍在Eclipse IDE工具中开发Struts 2应用,并且详细介绍Struts 2配置文件的各个细节。

    3.1  Struts 1MVC实现

    Struts 1是世界上最“古老”的MVC框架,它出现于2001年。Struts 1以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的所有请求。Struts 1框架有3个重要组成部分:Action、ActionForm和ActionForward对象。

    3.1.1  下载和安装Struts 1框架

    本节的示例程序基于Struts 1的1.2.9版,请读者也下载该版本的Struts 1框架,下载和安装Struts 1框架请按如下步骤进行。

     登录struts.apache.org站点,下载Struts的合适版本。解压缩下载到的压缩包,解压缩后,发现有如下文件结构:

    —  contrib:该路径下存放了Struts 1表达式语言支持的类库和标签库文件。

    —  lib:该路径下存放了Struts 1框架的核心类库。

    —  webapps:该路径下存放了Struts 1框架的示例应用及文档应用。

    — 另外还一些关于Struts的说明和LICENSE等文档

     将lib下的JAR文件全部复制到WEB-INF/lib下,并将TLD文件全部复制到WEB-INF下,再将validator-rules.xml文件也复制到WEB-INF下。如果需要用到Struts-EL(表达式)语言,还应将contrib下的JAR文件复制到WEB-INF/lib下。

     为了在编译程序时可以导入Struts 1类库,还应将struts.jar文件增加到环境变量中。

    3.1.2  实现ActionForm

    Struts 1使用单独的ActionForm封装请求参数,当用户提交一个请求时,Struts 1将使用单独的ActionForm来封装所有的请求参数。从结构上看,ActionForm就是一个POJO:它需要为用户的每个请求参数都提供一个对应的属性,并为该属性设置相应的setter和getter方法——但ActionForm的设计不是POJO,它必须继承Struts 1的ActionForm基类。

    下面是一个简单的登录页面,包含两个表单域,分别代表用户名和密码。该登录页面的代码如下:

    <%@ page language="java" contentType="text/html;charset=gb2312" errorPage=""%>

    <!--  导入Struts的三个标签库-->

    <%@include file="taglibs.jsp"%>

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    <!--  使用国际化资源文件的key输出标题-->

    <title><bean:message key="login"/></title>

    </head>

    <body>

    <!-- 输出登录页面标题 -->

    <h3><bean:message key="loginTitle"/></h3>

    <!-- 输出Action处理完后的错误信息。 -->

    <font color="red">${requestScope.err}</font>

    <!-- 通过messagePresent判断输入校验后的出错提示是否存在 -->

    <logic:messagesPresent>

                                     <!-- 输出出错提示 -->

                                     <bean:message key="errors.header"/>

                                     <ul>

                                     <html:messages id="error">

                                      <li><bean:write name="error"/></li>

                                     </html:messages>

       </ul><hr />

    </logic:messagesPresent>

    <!-- 下面是登录表单 -->

    <html:form action="login.do">

                                     <!-- 使用国际化信息来输出标签 -->

                                     <bean:message key="username"/><html:text property="username"/><br>

                                     <bean:message key="pass"/><html:password property="pass"/><br>

                                     <html:submit><bean:message key="login"/></html:submit><br>

    </html:form>

    </body>

    </html>

    在浏览器中浏览该页面时,看到该页面包含了一个简单的登录表单。该页面的界面如图3.1所示。

    该页面中有两个表单域,这两个表单域封装了需要向服务器发送的请求参数,对于Strurts应用而言,请求参数是通过ActionForm来封装的,ActionForm非常类似一个POJO(定义几个属性,为每个属性提供setter和getter方法),但该ActionFrom需要继承ActionForm,或者是它的子类。因为本应用使用了Struts的校验框架,因此本应用中的ActionForm继承了ValidatorForm类。下面是本应用中ActionForm类的代码:

    public class LoginForm extends ValidatorForm

    {

                                     //下面两个属性用于封装两个表单域的请求参数

        private String username;

                                     private String pass;

        //以下是属性字段的系列get、set方法

        public String getUsername()

        {

                                        return username;

        }

        public void setUsername(String username)

        {

                                        this.username = username;

        }

        public String getPass()

        {

                                        return pass;

        }

        public void setPass(String pass)

        {

                                        this.pass = pass;

        }

    }

    上面ActionForm类的代码非常简单,除了该类需要继承ValidatorForm之外。也正是因为该ActionForm继承了ValidatorForm,从而导致了该类的污染,降低了该类的代码复用。

    对于Struts 1而言,ActionForm类是一个既烦琐又没有技术含量的类,写起来难免让程序员觉得意兴索然。虽然有很多IDE(集成开发环境)可以自动生成该ActionForm类,但Struts 1框架也感觉到大量重复书写该类是一个负担,后来提供了动态ActionForm,让人可以避免书写ActionForm类。

     注意  Struts 1中的ActionForm类是一个非常简单的类,它实质上是一个普通的JavaBean,但必须继承ActionForm类。除此之外,ActionForm还可以使用动态FormBean,从而允许通过配置文件来定义ActionForm。

    3.1.3  实现Action

    Action就是用于处理用户请求的业务控制器,当用户请求发送到ActionServlet后,ActionServlet拦截到用户请求,将请求转发到系统的业务控制器处理。ActionServlet在转发用户请求时,会将请求参数封装成ActionForm实例,并将该 ActionForm实例转发给Action实例。

    Action实例从ActionForm中取出用户请求参数,然后调用业务逻辑组件处理用户请求,并根据处理结果,调用不同的视图页面来呈现处理结果。

    下面是系统的Action处理类代码。

    public class LoginAction extends Action

    {

                                      //必须重写该execute方法,该方法用于处理用户请求

                                      public ActionForward execute(ActionMapping mapping, ActionForm form,

                                      HttpServletRequest request, HttpServletResponse response)throws

                                            Exception

                                      {

                                        //获取封装用户请求参数的ActionForm实例

                                        LoginForm loginForm = (LoginForm)form;

                                        //从ActionForm中取出用户请求参数

                                        String username = loginForm.getUsername();

                                        String pass = loginForm.getPass();

                                        //处理用户请求

                                        if (username != null && username.equals("scott"))

                                        {

                                            return mapping.findForward("welcome");

                                        }

                                        else

                                        {

                                            return mapping.findForward("error");

                                        }

        }

    }

    上面的Action代码非常简单,甚至没有调用任何业务逻辑组件,只是直接判断用户请求参数的用户名和密码是否为scott和tiger,如果用户名和密码正确,则返回welcome的ActionForward,否则返回error的ActionForward。

     注意  ActionForward就是一个逻辑视图,通过在配置文件中定义ActionFoward的映射,完成逻辑视图名和实际视图资源之间的映射。

    Struts 1的Action类与Struts 2的Action类有一定的类似性,都通过调用execute方法来处理用户请求。但最大的区别在于Struts 1 Action的execute方法与Servlet API耦合,但Struts 2 Action类的execute方法无需与Servlet API耦合。

    3.1.4  配置Struts 1Action

    实现了Struts 1的Action后,还需要在struts-config.xml文件中配置Action,配置Action需要指定Action的实现类,以及Action处理请求的URL。

    配置Action时,还应该配置该Action对应的ActionForm,每个ActionForm使用一个<form-bean.../>元素定义。定义Action和ActonForm之间的关联关系时,在定义Action的<action../>元素中通过name属性指定与此Action关联的ActionForm。

    因为本应用还使用了Struts 1的数据校验框架,因此配置<action.../>元素时,还应该增加validate属性,并将该属性值设置成true;还需要增加input属性,该属性指向输入校验失败后转入的视图资源。

    下面是本应用的struts-config.xml文件代码。

    <?xml version="1.0" encoding="GBK"?>

    <!-- 指定Struts 1配置文件的DTD信息 -->

    <!DOCTYPE struts-config PUBLIC

              "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"

              "http://struts.apache.org/dtds/struts-config_1_2.dtd">

    <!-- 指定Struts 1配置文件的根元素 -->

    <struts-config>

                                     <!-- 所有的ActionForm都应该在form-beans元素中定义 -->

                                     <form-beans>

                                        <!-- 每个form-bean定义一个ActionForm -->

                                        <form-bean name="loginForm" type="lee.LoginForm"/>

                                     </form-beans>

                                     <!-- 所有的Action都放在action-mappings元素中定义 -->

                                     <action-mappings>

                                        <!-- 定义Action,其处理类为lee.LoginAction,对应的ActionForm为

                                        loginForm -->

                                        <action path="/login" type="lee.LoginAction" name="loginForm"

                                            validate="true" scope="request" input="/login.jsp">

                                            <!-- 当返回welcome的ActionForward时,转入welcome.jsp页 -->

                                            <forward name="welcome" path="/welcome.jsp" />

                                            <!-- 当返回error的ActionForward时,转入error.jsp页 -->

                                            <forward name="error" path="/error.jsp"/>

                                        </action>

                                     </action-mappings>

                                     <!-- 加载国际化资源文件 -->

                                     <message-resources parameter="MyResource"/>

                                     <!-- 加载Struts 1校验框架的插件 -->

                                     <plug-in className="org.apache.struts.validator.ValidatorPlugIn">

                                        <!-- 指定数据校验的两个校验规则文件 -->

                                              <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,

                                            /WEB-INF/validation.xml" />

                                        <set-property property="stopOnFirstError" value="true"/>

                                     </plug-in>

    </struts-config>

    正如前面看到的,页面中使用大量国际化标签来输出国际化消息,因此本应用必须加载相应的国际化资源文件,本应用的国际化资源文件的baseName是MyResource。指定应用的国际化资源文件通过<message-resources .../>元素指定。

    本应用使用了Struts 1的校验框架来完成输入校验,因此在本应用中加载了两个校验规则文件,其中validator-rules.xml文件是一个系统规则文件,通常无需修改;validation.xml文件是开发者定义的规则文件,该文件定义了需要校验的表单应该满足的规则。

    下面是校验规则文件的代码。

    <?xml version="1.0" encoding="GBK"?>

    <!-- 校验规则定义文件 -->

    <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation

              //DTD Commons Validator Rules Configuration 1.1.3//EN"

              "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">

    <!-- 校验规则文件的根元素 -->

    <form-validation>

      <formset>

                                     <!-- 定义需要校验的ActionForm,定义该ActionForm为loginForm -->

                                     <form name="loginForm">

                                        <!-- 定义username表单域必须满足必填、模式匹配两个规则 -->

                                        <field property="username" depends="required,mask">

                                            <arg key="username" position="0"/>

                                            <!-- 指定模式匹配在正则表达式 -->

                                       <var>

                                       <var-name>mask</var-name>

                                       <var-value>^w+$</var-value>

                                       </var>

                                        </field>

                                        <!-- 定义pass表单域必须满足必填、最小长度两个规则 -->

                                        <field property="pass" depends="required,minlength">

                                            <arg key="pass" position="0"/>

                                            <!-- 定义最小长度的规则 -->

                                       <arg name="minlength" key="${var:minlength}" resource="false"

                                                position="1"/>

                                       <var>

                                       <var-name>minlength</var-name>

                                       <var-value>4</var-value>

                                       </var>

                                        </field>

                                     </form>

      </formset>

    </form-validation>

    上面的规则文件定义了表单域的两个表单必须满足的规则:username是必填的,而且必须匹配^w+$的正则表达式;pass是必填的,并且至少有4位。

    定义了上面的校验规则后,如果用户的输入不能通过该输入校验,则系统自动转入配置<action .../>元素时指定的input属性所对应的视图资源。

    输入校验的提示信息都保存在国际化资源文件中,因此使用输入校验时,通常都建议使用国际化资源文件来保存校验提示信息。

     提示  使用输入校验时,通常建议使用国际化资源文件来保存校验失败的提示信息。

    3.1.5  完成应用流程

    经过上面步骤,可以非常清楚地看出上面示例应用的流程,用户进入系统的login.jsp页面,用户输入请求信息,发送请求。如果用户的请求参数不能通过输入校验,则系统将请求转发到login.jsp页面,否则请求将被转发到业务逻辑控制器Action处。

    Action处理用户请求参数,如果处理结果为success的ActionForward,则进入welcome.jsp页面;如果处理结果为error的ActionForward,则进入error.jsp页面。

    图3.2显示了该应用的顺序图。

     

    图3.2  系统顺序图

    如果用户输入的用户名正确、密码正确,用户登录成功,可以在welcome.jsp页面见到国际化的欢迎信息,并且通过Struts 1的标签输出登录的用户名。下面是welcome.jsp页面的代码。

    <%@ page contentType="text/html;charset=gb2312" errorPage="error.jsp"%>

    <!--  导入Struts的三个标签库-->

    <%@include file="taglibs.jsp"%>

    <html>

    <head>

    <!-- 通过Struts 1标签输出国际化的页面标题 -->

    <title><bean:message key="loginSuccess"/></title>

    </head>

    <body>

    <h3><bean:message key="loginSuccess"/></h3>

    <hr>

    <!-- 通过Struts 1标签输出国际化的欢迎信息,并把登录用的用户名作为参数传入 -->

    <bean:message key="welcome" arg0="${loginForm.username}"/>

    </body>

    </html>

    如果用户登录成功,将看到如图3.3所示的页面。

     

    图3.3  登录成功页面

    上面的Struts 1应用已经包含了Struts 1框架的核心部分,如ActionForm、Action实现,数据校验完成,应用的国际化支持等。

    通过上面的示例应用,我们看到Struts 1框架的最大缺点是:Struts 1应用的类与Servlet API耦合严重,而且大都需要继承Struts 1框架提供的基类,或实现Struts 1框架提供的接口,造成了代码污染。

    3.2  WebWorkMVC实现

    WebWork由OpenSymphony组织负责开发、维护,WebWork 2前身是Rickard Oberg开发的WebWork。现在我们所说的WebWork,通常指的是WebWork 2,它是由Xwork 1和WebWork 2两个项目组成的。

    WebWork紧紧以ServletDispatcher为核心,使用ServletDispatcher来处理所有的用户请求,它是整个WebWork框架的核心控制器。WebWork支持多视图表示,视图部分可以使用JSP、Velocity、FreeMarker、JasperReports、XML等。WebWork当前的最新版本是2.2.5,本节所使用的范例是基于该版本的WebWork完成的。由于WebWork已经全面整合到Struts 2框架中,故WebWork不会再有新版本发布,即不会有WebWork 2.3.X发布。

    3.2.1  WebWork的下载和安装

    WebWork当前的最新稳定版本是2.2.5,笔者建议读者也下载该版本。WebWork的下载和安装按如下步骤进行。

     登录http://www.opensymphony.com/webwork/站点,下载WebWork的最新稳定版,解压缩后发现如下的文件结构:

    —  dist:该路径下存放了WebWork的两个编译版本。

    —  docs:该路径下存放了WebWork的各种文档,包括WebWork的Wiki文档、API文档等。

    —  lib:该路径下存放了WebWork编译和运行所需的第三方类库,其中default路径下的所有JAR文件是WebWork应用必需的类库文件。

    —  src:该路径下存放了WebWork的源文件,如果使用WebWork过程中遇到无法解决的问题,可以参考该源文件解决。

    —  webapps:该路径下存放了WebWork的示例应用,这些示例应用是学习WebWork极好的资料。

    —  webwork-2.2.5.jar:该文件是WebWork框架的核心类库文件。

    —  webwork-src-2.2.5.jar:该压缩文件里包含了WebWork框架所有源代码。

    —  此外还有一些WebWork框架的编译脚本文件及各种说明文件。

    WebWork通常都作为Web框架使用,在Web应用中使用该框架。为Web应用增加WebWork框架的方法,与在Web应用中增加其他框架的方法完全一样。下面介绍如何安装WebWork框架。

     将webwork-2.2.5.jar文件复制到Web应用的WEB-INF/lib路径下,再将libdefault路径下的*.jar文件全部复制到WEB-INF/lib下。

     注意  使用WebWork框架必须有webwork-2.2.5.jar和libdefault路径下的全部JAR文件。至于lib路径下的其他JAR文件,则是可选的——只有当应用中需要使用这些第三方框架时,才需要这些类库文件。

     为了可以编译WebWork应用程序,建议将webwork-2.2.5.jar增加到CLASSPATH的环境变量中。当然也可以使用Ant工具,则无需增加环境变量。

    3.2.2  实现Action

    用户需要实现的WebWork核心组件依然是业务控制器,业务控制器就是一个Action,该Action也包含一个execute方法,但该方法不再包含任何Servlet API,也不包含任何WebWork API。这个Action与Struts 1的Action不同,它非常类似于一个普通的POJO。

    本应用的Action代码如下:

    public class LoginAction extends ActionSupport

    {

                                     //下面两个属性用于封装用户请求参数

                                      private String user;

                                      private String pass;

                                     //如下请求参数用于封装Action处理请求后的反馈

                                     private String tip;

                                     //user属性对应的setter和getter方法

                                      public String getUser()

                                      {

                                      return user;

                                      }

                                      public void setUser(String user)

                                      {

                                      this.user = user;

                                      }

                                     //pass属性对应的setter和getter方法

                                      public String getPass()

                                      {

                                      return pass;

                                      }

                                      public void setPass(String pass)

                                      {

                                      this.pass = pass;

                                      }

                                     //tip属性对应的setter和getter方法

                                      public String getTip()

                                      {

                                      return tip;

                                      }

                                     //tip属性对应的setter和getter方法

                                      public void setTip(String tip)

                                      {

                                      this.tip = tip;

                                      }

                                     //处理用户请求的execute方法

                                      public String execute() throws Exception

                                      {

                                      if (getUser().equals("scott")

                                            && getPass().equals("tiger"))

                                      {

                                            setTip(getText("loginSuccess"));

                                       return SUCCESS;

                                      }

                                      else

                                      {

                                            setTip(getText("loginFail"));

                                       return ERROR;

                                      }

                                      }

    }

    上面Action类的代码与Struts 1的Action类存在如下几个区别:

    —  WebWork的Action类无需与Servlet API耦合,从而可以更方便地进行单元测试。

    —  WebWork的Action类可无需ActionForm的支持,它本身包含了两个属性用于封装用户的请求参数。

    —  WebWork的Action类里包含的属性不仅可以封装用户请求参数,还可以封装Action的处理结果。

    —  WebWork的Action的execute方法返回的逻辑视图是一个标准字符串,而不是一个ActionForward对象。

    本应用中的Action继承了WebWork的ActionSupport基类,继承该基类导致了Action的代码污染,WebWork不强制要求Action类继承ActionSupport基类,但继承该基类可以更便捷地实现Action类,例如程序国际化。

    上面的Action实现类中包含了两个国际化信息,这两个国际化信息对应的key分别为loginSuccess和loginFail。为了在Action类中访问这两个国际化信息,需要在Action类中使用getText方法,该方法可以输出对应key的国际化信息。该getText方法正是来自于ActionSupport基类的方法。

     注意  WebWork的Action类不强制要求使用ActionForm类封装用户请求参数。但可使用模型驱动模式,在模型驱动模式下,Action不再负责封装请求参数,也不负责封装Action的处理结果。而是将请求参数和处理结果放在模型中封装——模型就是一个类似于ActionForm的对象,但该对象是一个POJO,无需继承任何WebWork基类。相对于直接使用Action封装请求参数的模式,模型驱动模式的编程更加复杂,因为需要额外增加一个模型类;但模型驱动模式更易理解:Action专门负责处理用户请求,而模型则专门负责封装数据。

    因为上面的Action封装了user和pass两个请求参数,故对应的JSP页面也应该包含这样两个表单域。下面是对应JSP页面的代码。

    <%@ page contentType="text/html;charset=GBK"%>

    <!-- 导入WebWork的标签库文件 -->

    <%@ taglib prefix="ww" uri="/webwork"%>

    <html>

    <head>

                                     <!-- 使用国际化信息标签输出国际化标题 -->

                                     <title><ww:text name="loginTitle"/></title>

    </head>

    <body>

    <ww:text name="loginTitle"/>

    <hr>

    <!-- 使用WebWork标签生成登录表单 -->

    <ww:form method="post" action="login">

                                     <!-- 生成登录用的用户名文本框 -->

                                     <ww:textfield name="user" label="%{getText('user')}"/>

                                     <!-- 生成登录用的密码文本框 -->

                                     <ww:textfield name="pass" label="%{getText('pass')}"/>

                                     <!-- 生成登录按钮 -->

                                     <ww:submit value="%{getText('submit')}"/>

    </ww:form>

    </body>

    </html>

    读者可能已经注意到,上面的表单定义中,大量使用了WebWork的标签库,借助于WebWork标签库,可以更简单的生成页面的表单元素。因此,上面页面中的表单定义中,甚至无需为表单域指定对应的Label信息,但可生成如下表单定义。图3.4显示了在浏览器中浏览该页面的效果。

    当使用<ww:textfield name="user" label="%{getText ('user')}"/>来生成一个文本框时,该标签负责生成一个名为user的文本输入框,该输入框对应的Label通过%{getText('user')表达式生成输出,该表达式负责输出一个国际化信息,该国际化信息对应的key为user。

    3.2.3  配置Action

    实现上面的Action后,需要在应用中配置该Action。WebWork使用一个xwork.xml文件来配置Action。

    在配置WebWork的Action之前,需要先配置Web应用加载WebWork框架。让Web应用加载WebWork框架就是配置WebWork的核心控制器,WebWork的核心控制器是ServletDispatcher。

    因为Web应用默认只加载web.xml文件,因此为了加载WebWork框架,必须在web.xml文件中配置WebWork的核心控制器:ServletDispatcher。修改后的web.xml文件如下:

    <?xml version="1.0" encoding="GBK"?>

    <!-- 指定Web应用配置文件的Schema信息 -->

    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.

                                        com/xml/ns/j2ee/web-app_2_4.xsd"

        version="2.4">

                                     <!-- 配置WebWork的核心Servlet -->

                                     <servlet>

                                        <!-- 指定WebWork核心Servlet的名字 -->

                                        <servlet-name>webwork</servlet-name>

                                        <!-- 指定WebWork核心Servlet的实现类 -->

                                         <servlet-class>com.opensymphony.webwork.dispatcher.ServletDispatcher

                                            </servlet-class>

                                      <load-on-startup>2</load-on-startup>

                                      </servlet>

                                     <!-- 配置WebWork核心Servlet的映射 -->

                                      <servlet-mapping>

                                        <!-- 配置WebWork核心Servlet映射的URL -->

                                      <servlet-name>webwork</servlet-name>

                                        <url-pattern>*.action</url-pattern>

                                     </servlet-mapping>

    </web-app>

    指定了上面的web.xml配置文件后,Web应用会自动加载WebWork框架,并加载Web应用的WEB-INF/classes路径下的xwork.xml文件。xwork.xml文件就是WebWork的配置文件,该文件主要配置应用的Action,以及Action对应的URL。

    <?xml version="1.0" encoding="GBK"?>

    <!-- 下面指定了WebWork配置文件的DTD信息 -->

    <!DOCTYPE xwork PUBLIC

                                     "-//OpenSymphony Group//XWork 1.1//EN"

                                     "http://www.opensymphony.com/xwork/xwork-1.1.dtd">

    <!-- xwork是WebWork配置文件的根元素 -->

    <xwork>

                                      <!-- 导入WebWork默认配置文件 -->

                                      <include file="webwork-default.xml" />

                                     <!-- WebWork默认将Action配置放在package下管理 -->

                                      <package name="default" extends="webwork-default">

                                        <!-- 指定login的Action,该Action的实现类为lee.LoginAction -->

                                             <action name="Login" class="lee.LoginAction">

                                            <!-- 指定input逻辑视图对应的物理视图资源 -->

                                       <result name="input">/login.jsp</result>

                                            <!-- 指定error逻辑视图对应的物理视图资源 -->

                                            <result name="error">/error.jsp</result>

                                            <!-- 指定success逻辑视图对应的物理视图资源 -->

                                            <result name="success">/success.jsp</result>

                                             </action>

                                      </package>

    </xwork>

    在上面的xwork.xml配置文件中,所有的Action放在package元素下管理,因为WebWork以包来管理所有的Action,所以全部的action元素都作为package元素的子元素存在。

     注意  WebWork以package来管理WebWork的Action,故所有的action元素都是package元素的子元素。

    配置action元素时,必须指定两个主要属性:name属性和class属性。其中name属性指定了该Action负责处理的URL,而class属性指定了该Action对应的实现类。例如上面的Action配置,该Action的name为login,表示该Action负责处理向login.action的URL发送的请求,处理请求的Java类为lee.LoginAction。

    实际上,WebWork可以包含两个配置文件,还有一个webwork.properties配置文件,这个文件是一个标准的属性文件,由一系列的WebWork属性的key和value组成。下面是webwork.properties文件的代码。

    #指定该WebWork应用处于开发模式下,如果出错,将输出更多出错调试信息

    webwork.devMode = true

    #指定每次请求都重载WebWork的配置文件

    webwork.configuration.xml.reload=true

    #指定WebWork应用的国际化资源文件的baseName为mess

    webwork.custom.i18n.resources=mess

    因为本应用处于开发阶段,故设置了WebWork应用的开发模式为true,并且每次请求都会重载WebWork的配置文件。上面配置文件的最后一行指定了WebWork的国际化资源文件的baseName为mess。

    上面配置WebWork应用时,指定了Action处理后逻辑视图名和物理视图之间的对应关系:"input"字符串对应/login.jsp页面,"error"字符串对应/error.jsp页面,"success"字符串对应/success.jsp页面。对比上面的Action类代码,发现该类的execute方法分别返回了SUCCESS和ERROR两个字符串常量——它们的定义包含在ActionSupport类中,其值分别为"success"和"error"字符串。

    这就是本系统流程:当用户输入的用户名为scott,且密码为tiger时,Action返回一个success的逻辑视图,该逻辑视图对应为/success.jsp页面;否则将进入/error.jsp页面。那么input逻辑视图的作用呢?input逻辑视图是输入校验失败后默认转入的视图页面。

     提示  与Struts 1类似,WebWork采用input逻辑视图来作为输入校验失败后转入的视图。

    3.2.4  完成数据校验

    WebWork可以支持手动完成输入校验,但这不是本应用将采用的方式,因为手动完成输入校验需要重写Action类的validate()方法,需要大量书写重复代码,相当烦琐。本应用利用了XWork的校验框架来完成数据校验,完成数据校验只需要在Action class文件所在的路径下存放对应的校验文件即可。

    下面是本应用的数据校验文件代码。

    <?xml version="1.0" encoding="gb2312"?>

    <!-- WebWork校验文件的DTD信息 -->

    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork

                                     Validator 1.0.2//EN"

                                     "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

    <!-- validators是校验文件的根元素 -->

    <validators>

                                     <!-- 使用表单校验器校验user表单域 -->

                                      <field name="user">

                                        <!-- 指定user表单域必须满足requiredstring(必填)规则 -->

                                      <field-validator type="requiredstring">

                                            <!-- 违反输入校验后的提示信息 -->

                                       <message key="user.required"/>

                                      </field-validator>

                                      </field>

                                      <!-- 使用表单校验器校验pass表单域 -->

                                      <field name="pass">

                                        <!-- 指定pass表单域必须满足requiredstring(必填)规则 -->

                                      <field-validator type="requiredstring">

                                       <message key="pass.required"/>

                                      </field-validator>

                                        <!-- 指定pass表单域必须满足stringlength(长度范围)规则 -->

                                      <field-validator type="stringlength">

                                            <!-- 指定最小长度 -->

                                       <param name="minLength">3</param>

                                            <!-- 指定最大长度 -->

                                       <param name="maxLength">6</param>

                                       <message key="pass.length"/>

            </field-validator>

        </field>

    </validators>

    上面的校验文件使用了两个表单校验器:requiredstring和stringlength,分别对应用的两个表单域进行校验,分别校验用户名必须满足必填规则,密码必须满足必填且字符串长度必须在3和6之间的规则。

    如果用户输入不满足该规则,则看到如图3.5所示的界面。

     

    图3.5  输入校验的效果

    通过上面的示范代码,可以看出,结合XWork的校验框架,可以大大简化WebWork应用的数据校验。

    对比上面的Struts 1框架和WebWork框架的使用,不难发现WebWork与Struts 2的设计更类似。

    3.2.5  完成应用流程

    正如我们见到的,如果我们输入了合适的用户名和密码,Action处理完用户请求后,将会封装一个名为tip的属性在结果里,并转入success的逻辑视图,该逻辑视图对应了/success.jsp页面。该页面的代码非常简单,它只是简单地使用WebWork标签来输出tip的提示信息。页面代码如下:

    <%@ page contentType="text/html;charset=GBK"%>

    <!-- 导入WebWork的标签库 -->

    <%@ taglib prefix="ww" uri="/webwork"%>

    <html>

    <head>

                                     <!-- 输出tip提示信息 -->

                                     <title><ww:property value="tip"/></title>

    </head>

    <body>

    <h3><ww:property value="tip"/></h3>

    <!-- 使用WebWork的国际化标签来输出国际化提示 -->

    <ww:text name="welcomeMsg">

                                     <!-- 传入国际化提示信息的参数 -->

                                     <ww:param value="user"/>

    </ww:text>

    </body>

    </html>

    在上面的页面中,我们使用了<ww.text .../>标签来输出国际化消息,该标签输出的国际化消息如下:

    welcomeMsg=欢迎您,{0},您已经成功登录本系统!

    看到上面的国际化消息需要传入一个参数,我们通过为<ww:text .../>标签指定一个<ww:param .../>子标签来传入参数:第一个<ww:param .../>子元素为第一个参数指定值,第二个<ww:param .../>子元素为第二个参数指定值……依此类推。

    上面代码使用了<ww:param value="user"/>来传入参数,该参数的值就是Action中user属性值。当用户输入的用户名和密码正确时,将看到如图3.6所示的界面。

     

    图3.6  登录成功的界面

    3.3  Eclipse中开发Struts 2

    前面已经详细介绍了如何开发一个Struts 2应用,但没有使用任何IDE工具,那种开发方式虽然能让读者更清楚开发的细节,但对于开发效率却不如使用IDE工具的开发效率高。本节将以Eclipse为例,介绍如何在IDE工具中开发Struts 2应用。

    3.3.1  创建Web应用

    笔者所使用的Eclipse已经安装了MyEclipse插件,因此可以很方便地建立一个Web应用,并将其部署在Web服务器中。

    下面以Tomcat 5520为例,介绍如何在Eclipse中整合Tomcat服务器,新建一个Web应用,并将该应用部署到Tomcat服务器中。

    现在开始在Eclipse中整合Tomcat服务器,实际上,如果我们安装了MyEclipse插件,则可以在Eclipse中整合大部分的Java EE服务器(包括Web服务器)。但如果我们没安装任何插件,Eclipse则很难与任何Java EE服务器整合。

     提示  Eclipse必须安装了相应插件后才具有丰富的功能。为了开发Java EE应用,通常都推荐安装MyEclipse插件,该插件是一个商业产品,必须支付相应费用才可使用。

    为了在Eclipse中整合Tomcat服务器,请按如下步骤进行。

     单击Eclipse窗口里的“Window”菜单,在出现的“Window”的系列菜单项中选择“Preferences”菜单项,将弹出如图3.7所示的界面。

    该Preferences设置窗口是Eclipse大部分参数的设置窗口,该窗口还可设置Eclipse插件的相关属性。MyEclipse插件的相关属性就是在该窗口里设置的,而整合Java EE服务器只是MyEclipse插件的相关属性。

     单击图3.7所示窗口左边导航树中的“MyEclipse”节点,然后单击“MyEclipse”节点下的“Application Servers”子节点,将看到如图3.8所示的界面。

     

    图3.7  Eclipse的Preferences设置窗口

     

    图3.8  在Eclipse中整合应用服务器

     拖动图3.8所示窗口左边的垂直滚动条,我们可以发现大部分应用服务器的名字,例如Jboss、Jetty、Resin等,当然也可以发现我们需要使用的Tomcat节点,然后单击Tomcat 5节点,出现如图3.9所示的界面。

     

    图3.9  整合Tomcat5

     在图3.9右上方看到两个单选框:Enable和Disable,为了整合Tomcat,显然应该选中Enable单选框。选中该单选框后,还应该在下面的三个文本输入框内输入相应的地址,例如,Tomcat Home Directory里应该输入Tomcat的安装路径,笔者的Tomcat安装在D盘的tomcat5520路径下,故在该文本框内输入了D: omcat5520的内容。通常,一旦我们输入了正确的Tomcat安装路径,下面的两个文本框会自动输入,无需用户干预。

     单击图3.9所示窗口右下方的“OK”按钮,返回Eclipse主界面,Eclipse和Tomcat的整合成功。

    下面介绍如何在Eclipse中建立一个Web应用,在Eclipse中建立一个Web应用也可借助于MyEclipse的帮助。借助于MyEclipse建立Web应用按如下步骤进行。

     单击Eclipse主界面中的“File”菜单,在出现的菜单中单击“New”下的“Other...”菜单项,将弹出一个如图3.10所示的对话框。

     在如图3.10所示的对话框中,选中“Web Project”节点,表明将要创建一个Web应用,然后单击“Next”按钮,看到如图3.11所示的对话框。

        

    图3.10  新建Web应用的对话框                      图3.11  新建Web应用

     在如图3.11所示对话框的Project Name文本框中输入应用的名字,本应用使用Struts2Demo作为应用的名字,输入完成后可看到如图3.11所示的对话框。单击“Finish”按钮,新建Web应用成功。

    3.3.2  增加Struts 2支持

    为了让Web应用具有Struts 2支持功能,必须将Struts 2框架的核心类库增加到Web应用中。将Struts 2框架下lib路径下的struts2-core-2.0.6.jar、xwork-2.0.1.jar等Struts 2框架的核心类库复制到Web应用的lib路径下,也就是“%workspace%Struts2DemoWebRoot WEB-INFlib”路径下。

    返回Eclipse的主界面,在Eclipse主界面的左上角资源导航中看到了struts2Demo节点,选中该节点,然后按F5键,将看到Eclipse主界面左上角资源导航中出现如图3.12所示的界面。

    看到如图3.12所示的界面,表明该Web应用已经加入了Struts 2的核心类库,但还需要修改web.xml文件,让该文件负责加载Struts 2框架。

    在如图3.12所示的导航树中,单击“WEB-INF”节点前的加号,展开该节点,看到该节点下包含的web.xml文件子节点。

    单击web.xml文件节点,编辑该文件,编辑该文件没有丝毫特殊之处,同样是在web.xml文件中定义Struts 2的核心Filter,并定义该Filter所拦截的URL 模式。至此,该Web应用完全具备了Struts 2框架的支持。

    3.3.3  部署Struts 2应用

    本应用的功能非常类似于第2章所介绍的Struts 2应用,因此本节所使用的JSP页面与第2章所使用的JSP页面也非常类似,故此处不再给出这些JSP页面的代码。

    在Eclipse中添加JSP页面也是很简单的,此处不再赘述。

    建立了这些JSP页面后,单击Eclipse主界面上部署Web应用的工具按钮,部署Web应用和启动服务器的两个按钮如图3.13所示。

     

    图3.13  在Eclipse中部署Web应用和启动服务器的按钮

    在Eclipse中部署Web应用请按如下步骤进行。

     单击部署Web应用的按钮,弹出如图3.14所示的对话框。

     

    图3.14  部署Web应用的对话框

     在图3.14所示对话框的上面看到选择项目的下拉列表,选中需要部署的Web应用,例如本示例就是Struts2Demo。单击右边的“Add”按钮,该按钮用于添加想要部署到的Web服务器,将看到如图3.15所示的对话框。

     

    图3.15  部署到应用服务器

     在图3.15所示对话框上面的Server下拉列表中选中“Tomcat 5”选项,其他选项设置参照图3.15,然后单击“Finish”按钮,返回图3.14所示对话框,单击“OK”按钮,Web应用部署成功。

     Web应用部署成功后,单击如图3.13所示工具条中的“启动服务器”按钮旁的小三角,出现下拉菜单,选择“Tomcat 5”下的“Start”菜单项,如图3.16所示,启动Tomcat服务器。

     在浏览器中访问刚才的Struts2Demo应用,将可看到本应用登录页面。以Tomcat的端口为8888为例,应该在浏览器中访问如下地址:http://localhost:8888/Struts2Demo/ login.jsp,将看到如图3.17所示的界面。

           

    图3.16  启动服务器                         图3.17  部署成功后的登录界面

    在图3.17中看到该登录页面的文本框没有任何提示信息,按钮上也没有文本,这是因为本应用缺少国际化资源文件。增加该应用所需的国际化资源文件,该资源文件与前面应用的资源文件相同,此处不再给出。

    为了让Struts 2应用加载该国际化资源文件,还应该使用struts.properties文件,该文件内指定如下一行代码:

    #指定Struts 2的国际化资源文件的baseName为messageResource

    struts.custom.i18n.resources=messageResource

    至此,Struts 2应用已经获得了国际化支持。如果在浏览器中再次浏览该页面,将看到如图3.18所示的界面。

    3.3.4  增加应用的Action

    在Eclipse工具中新建一个Java类,该Java类的类名为“LoginAction”,其代码与第2章所使用的LoginAction类代码相同,将该类文件保存在Struts2Demo应用的src路径下的lee目录下。

     

    图3.18  增加了国际化资源文件后的登录页面

    新建一个Java文件的方法非常简单,此处不再赘述。本应用的Action类的代码与第2章的Action类完全一样,此处也不再给出。

    增加了Struts 2的Action类后,还需要增加对应的配置文件,也是通过单击Eclipse的“File”菜单,然后单击“New”下的“File”菜单项来操作的。

     提示  因为Eclipse暂时还没有专门的Struts 2插件,因此只能用最原始的方式来建立一个Struts 2的配置文件。等到专门的Struts 2插件被开发出来后,应该可以有更简单的方法来建立Struts 2的配置文件。

    建立该文件后,为该文件增加Struts 2的Action定义,定义该Action与前面介绍的基本一致,需要定义Action的name属性、class属性等。增加Action定义后的struts.xml文件代码如下:

    <?xml version="1.0" encoding="GBK"?>

    <!-- 指定Struts 2配置文件的DTD信息 -->

    <!DOCTYPE struts PUBLIC

            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

            "http://struts.apache.org/dtds/struts-2.0.dtd">

    <!-- 指定Struts 2配置文件的根元素 -->

    <struts>

                                     <!-- 所有的Action定义都应该放在package下 -->

                                     <package name="lee" extends="struts-default">

                                        <!-- 定义Action -->

                                      <action name="Login" class="lee.LoginAction">

                                            <!-- 定义三个逻辑视图和物理资源之间的映射 -->

                                       <result name="input">/login.jsp</result>

                                       <result name="error">/error.jsp</result>

                                       <result name="success">/welcome.jsp</result>

                                      </action>

                                      </package>

    </struts>

    至此,整个Struts 2应用完全建立成功,如果读者还需要增加数据校验,则可增加对应的校验文件,并将该文件放在与对应Action源文件的同一路径下即可。

    3.4  Struts 2的基本流程

    经过前面介绍,我们已经基本了解了Struts 2框架的MVC实现。大致上,Struts 2框架由3个部分组成:核心控制器FilterDispatcher、业务控制器和用户实现的业务逻辑组件。在这3个部分里,Struts 2框架提供了核心控制器FilterDispatcher,而用户需要实现业务控制器和业务逻辑组件。

    3.4.1  核心控制器:FilterDispatcher

    FilterDispatcher是Struts 2框架的核心控制器,该控制器作为一个Filter运行在Web应用中,它负责拦截所有的用户请求,当用户请求到达时,该Filter会过滤用户请求。如果用户请求以action结尾,该请求将被转入Struts 2框架处理。

    Struts 2框架获得了*.action请求后,将根据*.action请求的前面部分决定调用哪个业务逻辑组件,例如,对于login.action请求,Struts 2调用名为login的Action来处理该请求。

    Struts 2应用中的Action都被定义在struts.xml文件中,在该文件中定义Action时,定义了该Action的name属性和class属性,其中name属性决定了该Action处理哪个用户请求,而class属性决定了该Action的实现类。

    Struts 2用于处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理——因为用户实现的业务控制器并没有与Servlet API耦合,显然无法处理用户请求。而Struts 2框架提供了系列拦截器,该系列拦截器负责将HttpServletRequest请求中的请求参数解析出来,传入到Action中,并回调Action的execute方法来处理用户请求。

    显然,上面的处理过程是典型的AOP(面向切面编程)处理方式。图3.19显示了这种处理模型。

     

    图3.19  Struts 2的拦截器和Action

    从图3.19中可以看出,用户实现的Action类仅仅是Struts 2的Action代理的代理目标。用户实现的业务控制器(Action)则包含了对用户请求的处理。用户的请求数据包含在HttpServletRequest对象里,而用户的Action类无需访问HttpServletRequest对象。拦截器负责将HttpServletRequest里的请求数据解析出来,并传给业务逻辑组件Action实例。

    3.4.2  业务控制器

    正如从图3.19所看到的,业务控制器组件就是用户实现Action类的实例,Action类里通常包含了一个execute方法,该方法返回一个字符串——该字符串就是一个逻辑视图名,当业务控制器处理完用户请求后,根据处理结果不同,execute方法返回不同字符串   ——每个字符串对应一个视图名。

    程序员开发出系统所需要的业务控制器后,还需要配置Struts 2的Action,即需要配置Action的如下三个部分定义:

    —  Action所处理的URL。

    —  Action组件所对应的实现类。

    —  Action里包含的逻辑视图和物理资源之间的对应关系。

    每个Action都要处理一个用户请求,而用户请求总是包含了指定URL。当Filter Dispatcher拦截到用户请求后,根据请求的URL和Action处理URL之间的对应关系来处理转发。

    3.4.3  Struts 2的模型组件

    实际上,模型组件已经超出了MVC框架的覆盖范围。对于Struts 2框架而言,通常没有为模型组件的实现提供太多的帮助。

    Java EE应用里的模型组件,通常指系统的业务逻辑组件。而隐藏在系统的业务逻辑组件下面的,可能还包含了DAO、领域对象等组件。

    通常,MVC框架里的业务控制器会调用模型组件的方法来处理用户请求。也就是说,业务逻辑控制器不会对用户请求进行任何实际处理,用户请求最终由模型组件负责处理。业务控制器只是中间负责调度的调度器,这也是称Action为控制器的原因。

    图3.20显示了这种处理流程。

     提示  在图3.20中看到Action调用业务逻辑组件的方法。当控制器需要获得业务逻辑组件实例时,通常并不会直接获取业务逻辑组件实例,而是通过工厂模式来获得业务逻辑组件的实例;或者利用其他IoC容器(如Spring容器)来管理业务逻辑组件的实例。

    3.4.4  Struts 2的视图组件

    Struts 2已经改变了Struts 1只能使用JSP作为视图技术的现状,Struts 2允许使用其他的模板技术,如FreeMarker、Velocity作为视图技术。

    当Struts 2的控制器返回逻辑视图名时,逻辑视图并未与任何的视图技术关联,仅仅是返回一个字符串,该字符串作为逻辑视图名。

    当我们在struts.xml文件中配置Action时,不仅需要指定Action的name属性和class属性,还要为Action元素指定系列result子元素,每个result子元素定义一个逻辑视图和物理视图之间的映射。前面所介绍的应用都使用了JSP技术作为视图,故配置result子元素时没有指定type属性,默认使用JSP作为视图资源。

    如果需要在Struts 2中使用其他视图技术,则可以在配置result子元素时,指定相应的type属性即可。例如,如果需要使用FreeMarker,则为result指定值为freemarker的type属性;如果想使用Velocity模板技术作为视图资源,则为result指定值为velocity的type属性……

    3.4.5  Struts 2的运行流程

    经过上面介绍,我们发现Struts 2框架的运行流程非常类似于WebWork框架的流程。

     提示  在Struts 2的官方站点,我们可以找到如下说法:Essentially,Struts 2.0 is the technical equivalent of WebWork 2.3。Aside from the package and property renaming,it isn't much different than,say,migrating from WebWork 2.1 to 2.2——意思是说:Struts 2.0技术等同于WebWork 2.3框架,除了包和属性被改名外。从WebWork 2.2迁移到Struts 2不会比从WebWork 2.1迁移到WebWork 2.2更复杂。

    这里我们可以看到,Struts 2其实就是WebWork 2.2的升级版,这也就不难理解:为什么WebWork和Struts 2如此相似!

    因此,Struts 2的运行流程与WebWork的运行流程完全相同,读者可以参看图1.8来了解Struts 2的运行流程。

    3.5  Struts 2的基本配置

    前面大致了解了Struts 2框架的基本内容,但这些基本内容都必须建立在Struts 2的配置文件基础之上,这些配置文件的配置信息也是Struts 2应用的核心部分。

    3.5.1  配置web.xml文件

    任何MVC框架都需要与Web应用整合,这就不得不借助于web.xml文件,只有配置在web.xml文件中Servlet才会被应用加载。

    通常,所有的MVC框架都需要Web应用加载一个核心控制器,对于Struts 2框架而言,需要加载FilterDispatcher,只要Web应用负责加载FilterDispatcher,FilterDispatcher将会加载应用的Struts 2框架。

    因为Struts 2将核心控制器设计成Filter,而不是一个普通Servlet。故为了让Web应用加载FilterDispacher,只需要在web.xml文件中配置FilterDispatcher即可。

    配置FilterDispatcher的代码片段如下:

    <!-- 配置Struts 2框架的核心Filter -->

    <filter>

                                     <!-- 配置Struts 2核心Filter的名字 -->

                                     <filter-name>struts</filter-name>

                                     <!-- 配置Struts 2核心Filter的实现类 -->

                                      <filter-class>org.apache.struts2.dispatcher.FilterDispatcher

                                        </filter-class>

                                      <init-param>

                                        <!-- 配置Struts 2框架默认加载的Action包结构 -->

                                         <param-name>actionPackages</param-name>

                                      <param-value>org.apache.struts2.showcase.person</param-value>

                                     </init-param>

                                     <!-- 配置Struts 2框架的配置提供者类 -->

                                      <init-param>

                                         <param-name>configProviders </param-name>

                                      <param-value>lee.MyConfigurationProvider</param-value>

                                     </init-param>

    </filter>

    正如上面看到的,当配置Struts 2的FilterDispatcher类时,可以指定一系列的初始化参数,为该Filter配置初始化参数时,其中有3个初始化参数有特殊意义:

    —  config:该参数的值是一个以英文逗号(,)隔开的字符串,每个字符串都是一个XML配置文件的位置。Struts 2框架将自动加载该属性指定的系列配置文件。

    —  actionPackages:该参数的值也是一个以英文逗号(,)隔开的字符串,每个字符串都是一个包空间,Struts 2框架将扫描这些包空间下的Action类。

    —  configProviders:如果用户需要实现自己的ConfigurationProvider类,用户可以提供一个或多个实现了ConfigurationProvider接口的类,然后将这些类的类名设置成该属性的值,多个类名之间以英文逗号(,)隔开。

    除此之外,还可在此处配置Struts 2常量,每个<init-param>元素配置一个Struts 2常量,其中<param-name>子元素指定了常量name,而<param-value>子元素指定了常量value。

     提示  关于Struts 2常量的讲解,请参阅本书的4.1.2节。

    在web.xml文件中配置了该Filter,还需要配置该Filter拦截的URL。通常,我们让该Filter拦截所有的用户请求,因此使用通配符来配置该Filter拦截的URL。

    下面是配置该Filter拦截URL的配置片段:

    <!-- 配置Filter拦截的URL -->

    <filter-mapping>

                                     <!-- 配置Struts 2的核心FilterDispatcher拦截所有用户请求 -->

                                     <filter-name>struts</filter-name>

                                      <url-pattern>/*</url-pattern>

    </filter-mapping>

    配置了Struts 2的核心FilterDispatcher后,基本完成了Struts 2在web.xml文件中的配置。

    如果Web应用使用了Servlet 2.3以前的规范,因为Web应用不会自动加载Struts 2框架的标签文件,因此必须在web.xml文件中配置加载Struts 2标签库。

    配置加载Struts 2标签库的配置片段如下:

    <!-- 手动配置Struts 2的标签库 -->

    <taglib>

                                     <!-- 配置Struts 2标签库的URI -->

                                     <taglib-uri>/s</taglib-uri>

                                     <!-- 指定Struts 2标签库定义文件的位置 -->

                                     <taglib-location>/WEB-INF/struts-tags.tld</taglib-location>

    </taglib>

    在上面配置片段中,指定了Struts 2标签库配置文件物理位置:/WEB-INF/struts- tags.tld,因此我们必须手动复制Struts 2的标签库定义文件,将该文件放置在Web应用的WEB-INF路径下。

    如果Web应用使用Servlet 2.4以上的规范,则无需在web.xml文件中配置标签库定义,因为Servlet 2.4规范会自动加载标签库定义文件。

     提示  Struts 2的标签库定义文件包含在struts2-core-2.0.6.jar文件里,在struts2-core-2.0.6.jar文件的META-INF路径下,包含了一个struts-tag.tld文件,这个文件就是Struts 2的标签库定义文件,Servlet 2.4规范会自动加载该标签库文件。

    对于Servlet 2.4以上的规范,Web应用自动加载该标签库定义文件。加载struts-tag.tld标签库定义文件时,该文件的开始部分包含如下代码片段:

    <taglib>

                                     <!-- 定义标签库的版本 -->

                                     <tlib-version>2.2.3</tlib-version>

                                     <!-- 定义标签库所需的JSP版 -->

                                     <jsp-version>1.2</jsp-version>

                                     <short-name>s</short-name>

                                     <!-- 定义Struts 2标签库的URI -->

                                     <uri>/struts-tags</uri>

                                     ...

    </taglib>

    因为该文件中已经定义了该标签库的URI:struts-tags,这就避免了在web.xml文件中重新定义Struts 2标签库文件的URI。

    3.5.2  struts.xml配置文件

    Struts框架的核心配置文件就是struts.xml配置文件,该文件主要负责管理Struts 2框架的业务控制器Action。

    在默认情况下,Struts 2框架将自动加载放在WEB-INF/classes路径下的struts.xml文件。在大部分应用里,随着应用规模的增加,系统中Action数量也大量增加,导致struts.xml配置文件变得非常臃肿。

    为了避免struts.xml文件过于庞大、臃肿,提高struts.xml文件的可读性,我们可以将一个struts.xml配置文件分解成多个配置文件,然后在struts.xml文件中包含其他配置文件。

    下面的struts.xml文件中就通过include手动导入了一个配置文件:struts-part1.xml文件,通过这种方式,就可以将Struts 2的Action按模块配置在多个配置文件中。

    <?xml version="1.0" encoding="UTF-8" ?>

    <!-- 指定Struts 2配置文件的DTD信息 -->

    <!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

    <!-- 下面是Struts 2配置文件的根元素 -->

    <struts>

                                     <!-- 通过include元素导入其他配置文件 -->

                                      <include file="struts-part1.xml" />

                                     ...

    </struts>

    通过这种方式,Struts 2提供了一种模块化的方式来管理struts.xml配置文件。

    除此之外,Struts 2还提供了一种插件式的方式来管理配置文件。用WinRAR等解压缩软件打开struts2-core-2.0.6.jar文件,看到如图3.21所示的文件结构,在光标选中的一行,看到有一个struts-default.xml文件。

     

    图3.21  struts2-core-2.0.6.jar压缩文件的文件结构

    查看struts-default.xml文件,看到该文件代码片段如下:

    <?xml version="1.0" encoding="UTF-8" ?>

    <!-- 指定Struts 2配置文件的DTD信息 -->

    <!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

    <!-- Struts 2配置文件的根元素 -->

    <struts>

                                     <!-- 下面定义了Struts 2框架的一些基础Bean  -->

                                     <bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" />

                                     <bean type="com.opensymphony.xwork2.ObjectFactory" name="struts"

                                        class="org.apache.struts2.impl.StrutsObjectFactory" />

                                     ....

                                      <!-- 下面是一些静态注入Bean定义 -->

                                            <bean class="com.opensymphony.xwork2.util.OgnlValueStack" static="true" />

                                      <bean class="org.apache.struts2.dispatcher.Dispatcher" static="true" />

                                     ...

                                     <!-- 下面定义Struts 2的默认包空间 -->

                                      <package name="struts-default">

                                        <!-- 定义Struts 2内建支持的结果类型 -->

                                      <result-types>

                                            <!-- 定义Action链Result类型 -->

                                       <result-type name="chain" class="com.opensymphony.xwork2.

                                                ActionChainResult"/>

                                            <!-- 定义Dispatcher的Result类型,并设置default="true",

                                                指定该结果Result是默认的Result类型 -->

                                            <result-type name="dispatcher"

                                                    class="org.apache.struts2.dispatcher.Servlet

                                                        DispatcherResult" default="true"/>

                                            <!-- 定义FreeMarker的Result类型 -->

                                       <result-type name="freemarker"

                                                class="org.apache.struts2.views.freemarker.

                                                    FreemarkerResult"/>

                                            ...

                                      </result-types>

                                        <!-- 定义Struts 2内建的拦截器 -->

                                      <interceptors>

                                       <interceptor name="alias" class="com.opensymphony.xwork2.

                                                interceptor.AliasInterceptor"/>

                                            <interceptor name="autowiring"

                                                class="com.opensymphony.xwork2.spring.interceptor.

                                                    ActionAutowiringInterceptor"/>

                                            ...

                                       <!-- 定义基本拦截器栈 -->

                                       <interceptor-stack name="basicStack">

                                       <interceptor-ref name="exception"/>

                                       <interceptor-ref name="servlet-config"/>

                                       <interceptor-ref name="prepare"/>

                                       <interceptor-ref name="checkbox"/>

                                       <interceptor-ref name="params"/>

                                       <interceptor-ref name="conversionError"/>

                                       </interceptor-stack>

                                            <!-- 还有系列拦截器栈 -->

                                            ...

                                      </interceptors>

                                      <!-- 定义默认的拦截器栈引用 -->

                                      <default-interceptor-ref name="defaultStack"/>

                                      </package>

    </struts>

    上面的代码并未全部列出struts-default.xml文件,只是列出了每个元素的代表。上面配置文件中定义了一个名字为struts-default的包空间,该包空间里定义了Struts 2内建的Result类型,还定义了Struts 2内建的系列拦截器,以及由不同拦截器组成的拦截器栈,文件的最后还定义了默认的拦截器引用。

    这个struts-default.xml文件是Struts 2框架的默认配置文件,Struts 2框架每次都会自动加载该文件。查看我们前面使用的struts.xml文件,看到我们自己定义的package元素有如下代码片段:

    <!-- 指定Struts 2配置文件的根元素 -->

    <struts>

                                     <!-- 配置名为lee的包空间,继承struts-default包空间 -->

        <package name="lee" extends="struts-default">

                                        ...

        </package>

    </struts>

    在上面配置文件中,名为lee的包空间,继承了名为struts-default的包空间,struts-default包空间定义在struts-default.xml文件中。可见,Struts 2框架默认会加载struts-default.xml文件。

    不仅如此,Struts 2框架提供了一种类似Eclipse的扩展方式,它允许以一种“可插拔”的方式来安装插件,例如后面将要介绍的Spring插件、JSF插件等,它们都提供了一个类似struts2-Xxx-plugin.jar的文件——这个文件就是插件安装文件,只要将该文件放在Web应用的WEB-INF/lib路径下,Struts 2框架将自动加载该框架。

    使用WinRAR工具打开struts2-spring-plugin2.06.jar文件,找到一个struts-plugin.xml文件,打开该文件,该文件的代码如下:

    <?xml version="1.0" encoding="UTF-8" ?>

    <!-- 指定Struts 2的DTD信息 -->

    <!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

    <struts>

                                     <!-- 定义一个名字为spring的ObjectFactory -->

                                     <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring"

                                        class="org.apache.struts2.spring.StrutsSpringObjectFactory" />

                                      <!-- 指定名字为sping的ObjectFactory是Struts 2的ObjectFactory -->

                                      <constant name="struts.objectFactory" value="spring" />

                                     <!-- 定义名为spring-default的包空间 -->

                                      <package name="spring-default">

                                        <!-- 定义整合Spring框架所必需的拦截器列表 -->

                                      <interceptors>

                                       <interceptor name="autowiring"

                                                class="com.opensymphony.xwork2.spring.interceptor.

                                                    ActionAutowiringInterceptor"/>

                                       <interceptor name="sessionAutowiring"

                                                class="org.apache.struts2.spring.interceptor.

                                                    SessionContextAutowiringInterceptor"/>

                                      </interceptors>

                                      </package>

    </struts>

    在上面配置文件中,配置了Struts 2与Spring框架整合必需的常量、拦截器等——这也是Struts 2框架使用Spring插件必需的配置。只要将struts2-spring-plugin2.06.jar文件放在WEB-INF/lib路径下,Struts 2框架将自动加载该文件。

     提示  如果用户开发属于自己的Struts 2插件,只要将对应的struts-plugin. xml文件放在JAR文件中,Struts 2框架将自动加载该文件。通过这种方式,Struts 2框架允许使用可插拔的方式管理Struts 2的插件。

    3.5.3  struts.properties配置文件

    Struts 2框架有两个核心配置文件,其中struts.xml文件主要负责管理应用中的Action映射,以及该Action包含的Result定义等。除此之外,Struts 2框架还包含一个struts.properties文件,该文件定义了Struts 2框架的大量属性,开发者可以通过改变这些属性来满足应用的需求。

    struts.properties文件是一个标准的Properties文件,该文件包含了系列的key-value对象,每个key就是一个Struts 2属性,该key对应的value就是一个Struts 2属性值。

    struts.properties文件通常放在Web应用的WEB-INF/classes路径下。实际上,只要将该文件放在Web应用的CLASSPATH路径下,Struts 2框架就可以加载该文件。

    现在的问题是,struts.properties文件的哪些key是有效的?即struts.properties文件里包含哪些属性是有效的Struts 2属性。下面列出了可以在struts.properties中定义的Struts 2属性。

    —  struts.configuration:该属性指定加载Struts 2配置文件的配置文件管理器。该属性的默认值是org.apache.Struts2.config.DefaultConfiguration,这是Struts 2默认的配置文件管理器。如果需要实现自己的配置管理器,开发者则可以实现一个实现Configuration接口的类,该类可以自己加载Struts 2配置文件。

    —  struts.locale:指定Web应用的默认Locale。

    —  struts.i18n.encoding:指定Web应用的默认编码集。该属性对于处理中文请求参数非常有用,对于获取中文请求参数值,应该将该属性值设置为GBK或者GB2312。

     提示  当设置该参数为GBK时,相当于调用HttpServletRequest的setCharacterEncoding方法。

    —  struts.objectFactory:指定Struts 2默认的ObjectFactory Bean,该属性默认值是spring。

    —  struts.objectFactory.spring.autoWire:指定Spring框架的自动装配模式,该属性的默认值是name,即默认根据Bean的name属性自动装配。

    —  struts.objectFactory.spring.useClassCache:该属性指定整合Spring框架时,是否缓存Bean实例,该属性只允许使用true和false两个属性值,它的默认值是true。通常不建议修改该属性值。

    —  struts.objectTypeDeterminer:该属性指定Struts 2的类型检测机制,通常支持tiger和notiger两个属性值。

    —  struts.multipart.parser:该属性指定处理multipart/form-data的MIME类型(文件上传)请求的框架,该属性支持cos、pell和jakarta等属性值,即分别对应使用cos的文件上传框架、pell上传及common-fileupload文件上传框架。该属性的默认值为jakarta。

     注意  如果需要使用cos或者pell的文件上传方式,则应该将对应的JAR文件复制到Web应用中。例如,使用cos上传方式,则需要自己下载cos框架的JAR文件,并将该文件放在WEB-INF/lib路径下。

    —  struts.multipart.saveDir:该属性指定上传文件的临时保存路径,该属性的默认值是javax.servlet.context.tempdir。

    —  struts.multipart.maxSize:该属性指定Struts 2文件上传中整个请求内容允许的最大字节数。

    —  struts.custom.properties:该属性指定Struts 2应用加载用户自定义的属性文件,该自定义属性文件指定的属性不会覆盖struts.properties文件中指定的属性。如果需要加载多个自定义属性文件,多个自定义属性文件的文件名以英文逗号(,)隔开。

    —  struts.mapper.class:指定将HTTP请求映射到指定Action的映射器,Struts 2提供了默认的映射器:org.apache.struts2.dispatcher.mapper.DefaultActionMapper。默认映射器根据请求的前缀与Action的name属性完成映射。

    —  struts.action.extension:该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。

    —  struts.serve.static:该属性设置是否通过JAR文件提供静态内容服务,该属性只支持true和false属性值,该属性的默认属性值是true。

    —  struts.serve.static.browserCache:该属性设置浏览器是否缓存静态内容。当应用处于开发阶段时,我们希望每次请求都获得服务器的最新响应,则可设置该属性为false。

    —  struts.enable.DynamicMethodInvocation:该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。

    —  struts.enable.SlashesInActionNames:该属性设置Struts 2是否允许在Action名中使用斜线,该属性的默认值是false。如果开发者希望允许在Action名中使用斜线,则可设置该属性为true。

    —  struts.tag.altSyntax:该属性指定是否允许在Struts 2标签中使用表达式语法,因为通常都需要在标签中使用表达式语法,故此属性应该设置为true,该属性的默认值是true。

    —  struts.devMode:该属性设置Struts 2应用是否使用开发模式。如果设置该属性为true,则可以在应用出错时显示更多、更友好的出错提示。该属性只接受true和flase两个值,该属性的默认值是false。通常,应用在开发阶段,将该属性设置为true,当进入产品发布阶段后,则该属性设置为false。

    —  struts.i18n.reload:该属性设置是否每次HTTP请求到达时,系统都重新加载资源文件。该属性默认值是false。在开发阶段将该属性设置为true会更有利于开发,但在产品发布阶段应将该属性设置为false。

     提示  开发阶段将该属性设置了true,将可以在每次请求时都重新加载国际化资源文件,从而可以让开发者看到实时开发效果;产品发布阶段应该将该属性设置为false,是为了提供响应性能,每次请求都需要重新加载资源文件会大大降低应用的性能。

    —  struts.ui.theme:该属性指定视图标签默认的视图主题,该属性的默认值是xhtml。

    —  struts.ui.templateDir:该属性指定视图主题所需要模板文件的位置,该属性的默认值是template,即默认加载template路径下的模板文件。

    —  struts.ui.templateSuffix:该属性指定模板文件的后缀,该属性的默认属性值是ftl。该属性还允许使用ftl、vm或jsp,分别对应FreeMarker、Velocity和JSP模板。

    —  struts.configuration.xml.reload:该属性设置当struts.xml文件改变后,系统是否自动重新加载该文件。该属性的默认值是false。

    —  struts.velocity.configfile:该属性指定Velocity框架所需的velocity.properties文件的位置。该属性的默认值为velocity.properties。

    —  struts.velocity.contexts:该属性指定Velocity框架的Context位置,如果该框架有多个Context,则多个Context之间以英文逗号(,)隔开。

    —  struts.velocity.toolboxlocation:该属性指定Velocity框架的toolbox的位置。

    —  struts.url.http.port:该属性指定Web应用所在的监听端口。该属性通常没有太大的用户,只是当Struts 2需要生成URL时(例如Url标签),该属性才提供Web应用的默认端口。

    —  struts.url.https.port:该属性类似于struts.url.http.port属性的作用,区别是该属性指定的是Web应用的加密服务端口。

    —  struts.url.includeParams:该属性指定Struts 2生成URL时是否包含请求参数。该属性接受none、get和all三个属性值,分别对应于不包含、仅包含GET类型请求参数和包含全部请求参数。

    —  struts.custom.i18n.resources:该属性指定Struts 2应用所需要的国际化资源文件,如果有多份国际化资源文件,则多个资源文件的文件名以英文逗号(,)隔开。

    —  struts.dispatcher.parametersWorkaround:对于某些Java EE服务器,不支持HttpServlet Request调用getParameterMap()方法,此时可以设置该属性值为true来解决该问题。该属性的默认值是false。对于WebLogic、Orion和OC4J服务器,通常应该设置该属性为true。

    —  struts.freemarker.manager.classname:该属性指定Struts 2使用的FreeMarker管理器。该属性的默认值是org.apache.struts2.views.freemarker.FreemarkerManager,这是Struts 2内建的FreeMarker管理器。

    —  struts.freemarker.wrapper.altMap:该属性只支持true和false两个属性值,默认值是true。通常无需修改该属性值。

    —  struts.xslt.nocache:该属性指定XSLT Result是否使用样式表缓存。当应用处于开发阶段时,该属性通常被设置为true;当应用处于产品使用阶段时,该属性通常被设置为false。

    —  struts.configuration.files:该属性指定Struts 2框架默认加载的配置文件,如果需要指定默认加载多个配置文件,则多个配置文件的文件名之间以英文逗号(,)隔开。该属性的默认值为struts-default.xml,struts-plugin.xml,struts.xml,看到该属性值,读者应该明白为什么Struts 2框架默认加载struts.xml文件了。

    在有些时候,开发者不喜欢使用额外的struts.properties文件,Struts 2允许在struts.xml文件中管理Struts 2属性,在struts.xml文件中通过配置constant元素,一样可以配置这些属性。

    struts.xml配置片段如下:

    <?xml version="1.0" encoding="UTF-8" ?>

    <!-- 指定Struts 2的DTD信息 -->

    <!DOCTYPE struts PUBLIC

        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

        "http://struts.apache.org/dtds/struts-2.0.dtd">

    <struts>

                                     <!-- 通过constant元素配置Struts 2的属性 -->

                                      <constant name=" struts.custom.i18n.resources " value="mess" />

                                     ...

    </struts>

    上面代码片段配置了一个常用属性:struts.custom.i18n.resources,该属性指定了应用所需的国际化资源文件的baseName为mess。

     提示  Struts 2提供了两种方式来管理Struts 2的属性:既可以通过struts.properties文件来配置Struts 2属性,也可通过在struts.xml文件中配置constant元素来配置Struts 2属性。

    3.5.4  struts.xml文件结构

    struts.xml文件是整个Struts 2框架的核心,下面提供了一个最完整的struts.xml文件,这个文件没有任何实际意义,仅仅是一个struts.xml文件示范。

    <?xml version="1.0" encoding="GBK"?>

    <!-- 下面指定Struts 2配置文件的DTD信息 -->

    <!DOCTYPE struts PUBLIC

            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

            "http://struts.apache.org/dtds/struts-2.0.dtd">

    <!-- struts是Struts 2配置文件的根元素 -->

    <struts>

                                     <!-- 下面元素可以出现0次,也可以无限多次 -->

                                     <constant name="" value="" />

                                     <!-- 下面元素可以出现0次,也可以无限多次 -->

                                     <bean type="" name="" class="" scope="" static="" optional="" />

                                     <!-- 下面元素可以出现0次,也可以无限多次 -->

                                     <include file="" />

                                     <!-- package元素是Struts配置文件的核心,该元素可以出现0次,或者无限多次 -->

                                     <package name="必填的包名" extends="" namespace="" abstract=""

                                        externalReferenceResolver>

                                        <!-- 该元素可以出现,也可以不出现,最多出现一次 -->

                                        <result-types>

                                            <!-- 该元素必须出现,可以出现无限多次-->

                                            <result-type name="" class="" default="true|false">

                                                <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                <param name="参数名">参数值</param>*

                                            </result-type>

                                        </result-types>

                                        <!-- 该元素可以出现,也可以不出现,最多出现一次 -->

                                        <interceptors>

                                            <!-- 该元素的interceptor元素和interceptor-stack至少出现其中之一,

                                            也可以二者都出现 -->

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <interceptor name="" class="">

                                                <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                <param name="参数名">参数值</param>*

                                            </interceptor>

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <interceptor-stack name="">

                                                <!-- 该元素必须出现,可以出现无限多次-->

                                                <interceptor-ref name="">

                                                    <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                    <param name="参数名">参数值</param>*

                                                </interceptor-ref>

                                            </interceptor-stack>

                                        </interceptors>

                                        <!-- 下面元素可以出现0次,也可以无限多次 -->

                                        <default-interceptor-ref name="">

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <param name="参数名">参数值</param>

                                        </default-interceptor-ref>

                                        <!-- 下面元素可以出现0次,也可以无限多次 -->

                                        <default-action-ref name="">

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <param name="参数名">参数值</param>*

                                        </default-action-ref>?

                                        <!-- 下面元素可以出现0次,也可以无限多次 -->

                                        <global-results>

                                            <!-- 该元素必须出现,可以出现无限多次-->

                                            <result name="" type="">

                                                <!-- 该字符串内容可以出现0次或多次 -->

                                                映射资源

                                                <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                <param name="参数名">参数值</param>*

                                            </result>

                                        </global-results>

                                        <!-- 下面元素可以出现0次,也可以无限多次 -->

                                        <global-exception-mappings>

                                            <!-- 该元素必须出现,可以出现无限多次-->

                                            <exception-mapping name="" exception="" result="">

                                                异常处理资源

                                                <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                <param name="参数名">参数值</param>*

                                            </exception-mapping>

                                        </global-exception-mappings>

                                        <action name="" class="" method="" converter="">

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <param name="参数名">参数值</param>*

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <result name="" type="">

                                                映射资源

                                                <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                <param name="参数名">参数值</param>*

                                            </result>

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <interceptor-ref name="">

                                                <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                <param name="参数名">参数值</param>*

                                            </interceptor-ref>

                                            <!-- 下面元素可以出现0次,也可以无限多次 -->

                                            <exception-mapping name="" exception="" result="">

                                                异常处理资源

                                                <!-- 下面元素可以出现0次,也可以无限多次 -->

                                                <param name="参数名">参数值</param>*

                                            </exception-mapping>

                                        </action>

                                     </package>*

    <struts>

    上面的struts.xml配置文件是一个非常全面的配置文件,包含了Struts 2的全部配置元素。上面配置文件主要用于帮助对XML DTD不太熟悉的读者。

    实际上,如果读者需要熟悉XML文件的DTD(元素类型定义)语法,通过查看Struts 2配置文件的DTD信息,同样可以了解Struts 2配置文件的结构。下面是Struts 2配置文件的DTD文件代码。

    <!--

       Struts configuration DTD.

       Use the following DOCTYPE

      

       <!DOCTYPE struts PUBLIC

                                     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

                                     "http://struts.apache.org/dtds/struts-2.0.dtd">

    -->

    <!ELEMENT struts (package|include|bean|constant)*>

    <!ELEMENT package (result-types?, interceptors?, default-interceptor-ref?, default-action-ref?, global-results?, global-exception-mappings?, action*)>

    <!ATTLIST package

        name CDATA #REQUIRED

        extends CDATA #IMPLIED

        namespace CDATA #IMPLIED

        abstract CDATA #IMPLIED

        externalReferenceResolver NMTOKEN #IMPLIED

    <!ELEMENT result-types (result-type+)>

    <!ELEMENT result-type (param*)>

    <!ATTLIST result-type

        name CDATA #REQUIRED

        class CDATA #REQUIRED

        default (true|false) "false"

    <!ELEMENT interceptors (interceptor|interceptor-stack)+>

    <!ELEMENT interceptor (param*)>

    <!ATTLIST interceptor

        name CDATA #REQUIRED

        class CDATA #REQUIRED

    <!ELEMENT interceptor-stack (interceptor-ref+)>

    <!ATTLIST interceptor-stack

        name CDATA #REQUIRED

    <!ELEMENT interceptor-ref (param*)>

    <!ATTLIST interceptor-ref

        name CDATA #REQUIRED

    <!ELEMENT default-interceptor-ref (param*)>

    <!ATTLIST default-interceptor-ref

        name CDATA #REQUIRED

    <!ELEMENT default-action-ref (param*)>

    <!ATTLIST default-action-ref

        name CDATA #REQUIRED

    <!ELEMENT global-results (result+)>

    <!ELEMENT global-exception-mappings (exception-mapping+)>

    <!ELEMENT action (param|result|interceptor-ref|exception-mapping)*>

    <!ATTLIST action

        name CDATA #REQUIRED

        class CDATA #IMPLIED

        method CDATA #IMPLIED

        converter CDATA #IMPLIED

    <!ELEMENT param (#PCDATA)>

    <!ATTLIST param

        name CDATA #REQUIRED

    <!ELEMENT result (#PCDATA|param)*>

    <!ATTLIST result

        name CDATA #IMPLIED

        type CDATA #IMPLIED

    <!ELEMENT exception-mapping (#PCDATA|param)*>

    <!ATTLIST exception-mapping

        name CDATA #IMPLIED

        exception CDATA #REQUIRED

        result CDATA #REQUIRED

    <!ELEMENT include (#PCDATA)>

    <!ATTLIST include

        file CDATA #REQUIRED

    <!ELEMENT bean (#PCDATA)>

    <!ATTLIST bean

        type CDATA #IMPLIED

        name CDATA #IMPLIED

        class CDATA #REQUIRED

        scope CDATA #IMPLIED

        static CDATA #IMPLIED

        optional CDATA #IMPLIED

    <!ELEMENT constant (#PCDATA)>

    <!ATTLIST constant

        name CDATA #REQUIRED

        value CDATA #REQUIRED

    通过上面给出的struts.xml配置文件范例,以及Struts 2配置文件的DTD信息,我们已经可以全面掌握Struts 2配置文件的文件结构了,但struts.xml文件各配置元素的意义、各属性的相关含义依然不能深入了解。关于Struts 2配置文件各元素及各属性将在下一章深入介绍。

    3.6  本章小结

    因为Struts 2是以Struts 1和WebWork为基础的,故本章大致介绍了Struts 1和WebWork框架的MVC实现,并在此基础上侧重于介绍Struts 1和WebWork与Struts 2的延续性,以及Struts 2框架与Struts 1和WebWork的类似性。通过阅读本章,读者应该明白:Struts 2是通过WebWork发展起来的,而不是通过Struts 1发展起来的。

    本章还介绍了如何通过Eclipse IDE工具来开发Struts 2应用,Struts 2的配置文件,以及通过web.xml文件加载Struts 2框架。详细介绍了struts.properties文件,以及struts.xml配置文件的结构。关于深入配置struts.xml文件的元素,则放在下一章介绍

    魔由心生,有万境纵横,无一道清静,无量寿佛!
  • 相关阅读:
    【LeetCode-栈】栈排序
    【LeetCode-数组】旋转数组
    【LeetCode-数组】两个数组的交集 II
    【LeetCode-树】二叉树的层次遍历 II
    【LeetCode-字符串】Fizz Buzz
    【LeetCode-数组】数组的相对排序
    解决Oracle表中数据乱码的问题
    docker搭建mysql 用户名密码忘记了怎么办
    java中如何将string 转化成long
    http三次握手四次挥手
  • 原文地址:https://www.cnblogs.com/qihuan/p/4135066.html
Copyright © 2011-2022 走看看