zoukankan      html  css  js  c++  java
  • struts2框架 转载 精华帖

    一、Struts2简介

    参考《JavaEE 轻量级框架应用与开发—S2SH》

    Struts框架是流行广泛的一个MVC开源实现,而Struts2是Struts框架的新一代产品,是将Struts1和WebWork两种技术进行兼容、合并的全新的MVC框架。Struts2框架充分发挥了Struts1和WebWork这两种技术的优势,抛弃原来Struts1的缺点,使得Web开发更加容易。

    Struts1运行原理: 

    Struts1工作流程: 
    (1)客户端向Web应用发送请求,请求被核心控制器ActionServlet拦截; 
    (2)ActionServlet根据请求决定是调用业务逻辑控制器还是将请求转发给相应JSP页面; 
    (3)若调用业务逻辑控制器,则业务逻辑控制器再调用相应的模型来处理用户的请求; 
    (4)处理的结果再通过JSP呈现给用户

    Struts1缺点: 
    (1)Struts1仅支持JSP作为表现层技术 
    (2)在Model2的基础上发展得来,完全基于Servlet API,与Servlet API严重耦合,一旦脱离Web服务器,Action的测试将变得非常困难 
    (3)Action类必须继承其提供的Action基类,实现处理方法时又必须使用Struts1的专有API,这种入侵式设计的最大弱点在于:一旦系统需要重构,这些Action类将没有价值。

    Struts2结合Webwork的优势: 
    (1)Struts2支持更多表现层技术,有更好的适应性。 
    (2)Action无须跟Servlet API耦合,使得测试更加容易,同时提高代码重用性;而且不耦合任何Servlet API(拦截器机制) 
    (3)Struts2具有更好的模块化和可扩展性(插件机制)。

    二、Struts2框架结构与工作原理

    参考《JavaEE 轻量级框架应用与开发—S2SH》 
    博文推荐:struts2的核心与工作原理

    Struts2是以WebWork为核心,采用拦截器机制对用户的请求进行处理

    框架结构: 

    工作流程: 
    (1)客户端浏览器发送HTTP请求到Web应用 
    (2)Web容器将请求传递到标准ActionContextCleanUp过滤器以消除属性,而不让后续过滤器清楚,以延长Action中属性(包括自定义属性)的生命周期。ActionContextCleanUp作用 
    (3)再经过如stimesh等其他过滤器后,请求传递给StrutsPrepareAndExecuteFilter核心控制器 
    (4)StrutsPrepareAndExecuteFilter调用ActionMapper(Action映射器)确定调用哪个Action,再将控制权转移给ActionProxy代理 
    (5)ActionProxy代理调用配置管理器ConfigurationManager从配置文件struts.xml中读取配置信息,然后创建ActionInvocation对象 
    (6)ActionInvocation在调用拦截器链中的拦截器后再调用Action,根据Action返回的结果字符串查找对应的Result 
    (7)Result调用视图模板,再以相反的顺序执行拦截器链,返回HTTP响应 
    (8)HTTP响应以相反的顺序返回给核心控制器StrutsPrepareAndExecuteFilter以及其他web.xml中定义的过滤器,最终返回给客户端

    三、一个Struts2的简易Demo

    (1)导入Struts所需的Jar包,这里使用struts-2.3.31版本。下载地址 
    将struts-2.3.31appsstruts2-blank.war解压出来,并在struts2-blankWEB-INFlib中获取运行struts2的最小包 
     
    特别注意版本对应问题,由于不同版本的框架封装的内容会有所不同,当跟着教程做的时候,如果步骤完全相同但是出现异常,那么很大可能是因为版本迭代修改了部分内容所致。

    (2)在web.xml中配置核心控制器StrutsPrepareAndExecuteFilter 
    任何MVC框架需要与Web应用整合时都需要借助web.xml配置文件,由于StrutsPrepareAndExecuteFilter本质上是一个过滤器,在web.xml中用< filter>以及< filter-mapping>进行配置。而Web应用加载了StrutsPrepareAndExecuteFilter之后就有了Struts2的基本功能。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
        id="WebApp_ID" version="3.0">
      <display-name>Struts2Demo</display-name>
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
      <!-- 配置StrutsPrepareAndExecuteFilter核心控制器 -->
      <filter>
          <!-- 过滤器名 -->
          <filter-name>struts2</filter-name>
          <!-- StrutsPrepareAndExecuteFilter核心控制器的实现类 -->
          <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
      </filter>
      <filter-mapping>
          <!-- 过滤器名 -->
          <filter-name>struts2</filter-name>
          <!-- 过滤器过滤所有请求 -->
          <url-pattern>/*</url-pattern>
      </filter-mapping>
    </web-app>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    配置核心控制器StrutsPrepareAndExecuteFilter就是用其实现类过滤所有的请求。Struts-2.5.8版本中的核心控制器实现类更改为org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter

    (3)创建用户输入视图register.jsp

    <%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>用户注册</title>
      </head>
      <body>
        <form action="register.action" method="post">
            username:<input type="text" name="username"/><br/>
            password:<input type="password" name="password"/><br/>
            <input type="submit" value="注册"/><br/>
        </form>
      </body>
    </html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    < form>标签中的action属性为表单参数提交到的地址

    (4)创建业务Action

    public class RegisterAction {
        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;
        }
    
        public String execute() throws Exception{
            if(username!=null&&username.length()>0&&password!=null&&password.length()>0){
                return "success";
            }else{
                return "fail";
            }
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    如代码所示,RegisterAction是一个POJO,其属性应与input.jsp中的表单name属性对应。则当表单提交时,表单数据会通过setter()方法给Action对象赋值。 
    除此之外,Action类提供execute()方法返回结果字符串。

    Struts2中的Action类优势:

    • Action类完全是一个POJO,从而提高代码的课重用率;
    • Action类无须与任何Servlet API耦合,便于测试和应用;
    • Action类的业务处理方法execute()将String作为返回值可以映射到任何视图上,也可以是Action

    (5)在src下创建struts.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>
        <!-- 指定Struts2处于开发阶段,可以进行调试 -->
        <constant name="struts.devMode" value="true"/>
        <!-- Struts2的Action都必须配置在package里。这里使用默认的package -->
        <package name="default" namespace="/" extends="struts-default">
            <action name="register" class="action.RegisterAction">
                <!-- 配置execute()方法返回值与视图资源之间的映射关系 -->
                <!--  
                <result name="success">/result.jsp</result>
                <result name="error">/error.jsp</result>
                -->
                <result name="success">/index.jsp</result>
            </action>
        </package>
    </struts>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    极客学院Struts2配置文件Wiki 
    MyEclipse环境中,在src下创建的struts.xml在部署时会自动发布到WEB-INF/classes目录下 
    当Struts2生成ActionProxy代理时,需要访问Struts2的配置文件,有struts.xml(配置Action相关信息)与struts.properties(配置Struts2全局属性)两种。 
    如上的struts.xml,用< constant>元素设置Struts2的全局属性,在< package>中定义了一个名为register的Action,并指定了实现类以及< result>元素用来指定execute()方法返回值与视图资源之间的映射关系。 
    而struts.properties则以key=value的形式存储全局属性。 

    #指定Web应用的默认编码集
    struts.i18n.encoding=UTF-8
    #当struts.xml修改后是否重新加载该文件,在开发阶段最好打开
    struts.configuration.xml.reload=true
    #设置浏览器是否缓存静态内容,在开发阶段最好关闭
    struts.serve.static.browserCache=false
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Struts2中的全局属性详解 
    注意:若使用MyEclispe开发,则struts.xml在第一行会报错,主要是因为MyEclipse没有找到对应的dtd文件,但这完全不会影响运行。强迫症可以把struts-2.3.31srccoresrcmain esources目录下的dtd文件导入到MyElipse中,如何导入

    Demo运行流程分析: 
    (1)用户在input.jsp中输入数据提交后,所发送请求被核心控制器StrutsPrepareAndExecuteFilter过滤 
    (2)StrutsPrepareAndExecuteFilter调用ActionMapper,根据表单中action地址来确定名为register的Action类处理该请求 
    (3)然后Struts2框架读取配置文件struts.xml信息生成ActionProxy 
    (4)ActionProxy根据package中action元素中的name和class属性确定Action实现类为RegisterAction,并调用 
    (5)表单中的数据被setter()方法赋值给RegisterAction对象 
    (6)ActionProxy根据execute()返回值以及action元素中的result元素来确定返回哪个视图资源给用户

    四、Action业务处理

    1、Action实现方式 
    Action是Struts2应用的核心,用于处理用户的请求。 
    而Struts2框架实现Action类有以下三种方式

    • 普通POJO类,通常包含返回值为字符串的无参execute()方法
    • 实现Action接口
    • 继承ActionSupport类

    (1)POJO类 
    如demo所示,谨记Action中的属性名与表单中的元素属性名完全相同,且对于表单中的每个元素一定要有对应的getter/setter方法,这样Struts2才能够自动将请求参数赋值给对应的Action属性

    (2)实现Action接口方式 
    Struts2提供了一个Action接口,定义了Action处理类应该实现的通用规范

    /*
     * Action接口
     */
    public interface Action {
        //定义Action接口中包含的一些结果字符串
        public static final String ERROR="error";
        public static final String INPUT="input";
        public static final String LOGIN="login";
        public static final String NONE="none";
        public static final String SUCCESS="success";
    
        //处理方法
        public String execute() throws Exception;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 定义了5个字符串常量,用于规范execute()方法的返回值
    • 定义了execute()方法,规范Action类应该包含execute()方法,且方法返回值是字符串

    (3)继承ActionSupport类方式 
    Struts2框架为Action接口提供了一个实现类ActionSupport,该类提供了很多默认方法,如默认处理用户请求的方法、数据校验的方法、获取国际化信息的方法等 
    ActionSupport类是Struts2的默认Action处理类,如果配置Action类时没有指定class属性,系统自动默认使用ActionSupport类作为Action的处理类,对用户的请求进行处理。 
    API文档位置:struts-2.3.31/docs/xwork-apidocs/com/opensymphony/xwork2/ActionSupport.html

    2、结合ServletAPI 
    有些时候Action类不访问ServletAPI是不能实现业务逻辑的,例如跟踪HTTP Session的状态。Struts2也提供了一些方法访问ServletAPI 
    (1)通过ActionContext 
    在Struts2框架中,Action可以通过ActionContext类来访问ServletAPI 
    API文档位置:struts-2.3.31/docs/xwork-apidocs/com/opensymphony/xwork2/ActionContext.html

    (2)通过实现访问ServletAPI的接口并重写相应方法

    接口名描述
    ServletContextAware 实现该接口的Action可以直接访问Web应用的ServletContext实例
    ServletRequestAware 实现该接口的Action可以直接访问用户请求的HttpServletRequest实例
    ServletResponseAware 实现该接口的Action可以直接访问服务器响应的HttpServletResponse实例

    Struts2的特色是Action不再与任何ServletAPI耦合,所以不推荐这种方式直接访问Servlet API

    (3)通过ServletActionContext工具类 
    API文档位置:struts-2.3.31/docs/struts2-core-apidocs/org/apache/struts2/ServletActionContext.html

    五、Struts2配置详解

    参考《JavaEE 轻量级框架应用与开发—S2SH》 
    配置文件降低了各组件之间的耦合,是联系整个Struts2框架的纽带,通过配置文件将Struts2的核心控制器StrutsPrepareAndExecuteFilter、业务控制器Action以及视图等组件关联在一起,实现相应的功能。虽然Struts2提供了Convention插件来管理Action、result,但大多数情况下配置文件采用XML形式。

    1、全局属性的配置 
    可以通过配置全局属性来改变Struts2框架的一些默认行为,在Struts2中可以使用struts.xml、struts.properties以及web.xml进行配置 
    如果三个文件同时存在,则会按照struts.xml、struts.properties、web.xml的顺序加载常量,后面的会覆盖前面的,不过通常都在struts.xml中配置。 
    此外,struts.xml以及struts.properties应该保存在WEB-INF/classes目录下,MyEclipse环境下可以保存在src下 
    (1)通过< constant>元素在struts.xml中定义常量

    <struts>
        <!-- struts.i18n.encoding的值默认为UTF-8 -->
        <constant name="struts.i18n.encoding" value="GBK">
    </struts>
    • 1
    • 2
    • 3
    • 4

    (2)在struts.properties中定义

    struts.i18n.encoding=GBK
    • 1

    (3)通过元素在web.xml中配置

    <filter>
        <init-param>
            <param-name>struts.i18n.encoding </param-name>
            <param-value> GBK</param-value>
        </init-param>
    </filter>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、通过包< package>对核心组件进行组织和管理 
    如demo代码所示,Struts2配置文件中的包,是由多个Action、多个拦截器、多个拦截器引用组成的集合

    <struts>
        <!-- Struts2的Action都必须配置在package里。这里使用默认的package -->
        <package name="default" namespace="/" extends="struts-default">
            <action name="register" class="action.RegisterAction">
                <result name="success">/index.jsp</result>
            </action>
        </package>
    </struts>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    其中常用属性如下: 
    (1)name 
    指定包的名字,当存在多个包时作为唯一标识

    (2)extends 
    指定包所继承的其他包。 
    struts-default是Struts2框架默认的抽象包,包含了大量结果类型的定义、拦截器及其引用定义等,是配置Action的基础,因此定义包时都要继承struts-default包。 
    定义时,父包要先于子包;Action相同,后面的覆盖前面

    (3)namespace 
    指定包的命名空间,没有指定namespace值则为默认命名空间”/” 
    Struts2以命名空间的方式来管理Action,同一个命名空间不能有同名的Action 
    若namespace=”/”,则访问Action的URL为:http://ip:port/applicationname/register.action 
    若namespace=”/user”,则访问Action的URL为:http://ip:port/applicationname/user/register.action

    配置命名空间后,Struts2按照以下顺序搜索Action: 
    - 指定命名空间,不存在则往下搜索 
    - 默认命名空间,不存在则往下搜索 
    - 报错

    3、< include>元素包含其他配置文件 
    常用于团队模块化开发后的整合

    <struts>
        <include file="struts-others.xml"/>
    </struts>
    • 1
    • 2
    • 3

    < include>元素引用的xml文件必须是完整的Struts2配置文件,实际上在< include>元素引用文件时,会单独解析每个xml文件

    4、< action>配置 
    Struts2使用package下的action元素来配置Action,配置时需要指定action元素的name和class属性 
    - name:指定该Action所处理请求的URL,如name=register,则处理的URL为register.action 
    - class:指定Action实现类,如果没有指定,则默认使用ActionSupport类

    除此之外,action元素还可以使用method属性让Action调用指定方法而不是execute()方法来处理用户请求。 
    有时候,一个Action类中包含多个处理业务的方法,而不是execute()方法,如

    public class UserAction {
        private String user;
        public String getUser() {
            return user;
        }
        public void setUser(String user) {
            this.user = user;
        }
    
        public String add() throws Exception{
            return "add";
        }
        public String del() throws Exception{
            return "del";
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    若要调用add方法以及del方法,则要通过method属性

    <action name="addUser" class="action.UserAction" method="add"></action>
    <action name="delUser" class="action.UserAction" method="del"></action>
    • 1
    • 2

    像这种情况,Struts2还支持 * 通配符以减少冗余。利用通配符在定义Action的name属性时使用模式字符串 * ,接下来就可以在class、method属性以及< result>子元素中使用{N}的形式代表前面的第N个 * 所匹配的字符串。 
    如上述代码可转化为下面的代码:

    <action name="*User" class="action.UserAction" method="{1}"></action>
    • 1

    有了通配符以及{N},就可以通过设计name来大大简化代码的编写

    5、result配置 
    Struts2框架通过配置文件中< action>的< result>子元素配置逻辑视图名和物理视图资源之间的映射关系。 
    配置< result>元素时通常需要指定name和type属性: 
    - name属性指定逻辑视图名,也就是execute()返回的结果字符串 
    - type属性指定结果类型,默认为dispatcher,表示请求转发到JSP页面。

    (1)作用范围:局部result与全局result

    • 局部result——< result>元素作为< action>元素的子元素,针对该Action有效
    <struts>
        <package name="default" namespace="/" extends="struts-default">
            <action name="register" class="action.RegisterAction">
                <result name="success">/index.jsp</result>
            </action>
        </package>
    </struts>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 全局result——< result>元素作为< global-results>元素的子元素,针对所有Action有效
    <struts>
        <package name="default" namespace="/" extends="struts-default">               
                        <global-results>
                <result name="success">/index.jsp</result>
            </global-results>
            <action name="register" class="action.RegisterAction"></action>
        </package>
    </struts>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果一个Action中包含了与全局result同名的局部result,则局部result会覆盖全局result。亦即Action会首先搜索局部result,没有匹配项再搜索全局result。

    (2)结果类型 
    通过设置type属性值来确定返回的结果类型 
    Struts2学习之结果类型总结 
    Struts2返回JSON对象的方法总结

    6、异常处理 
    Struts2框架提供了声明式异常处理方式,通过在struts.xml文件中配置< exception-mapping>元素,指定exception与result属性确定映射关系 
    - exception属性,用于指定Action出现异常所映射的异常类型 
    - result属性,用于指定Action抛出异常时,系统转入属性值对应的< action>或< global-results>中的< result>元素

    根据作用范围的不同,又可分为 
    - 局部异常映射——< exception-mapping>作为< action>的子元素,针对该Action 
    - 全局异常映射——< exception-mapping>作为元素的子元素,针对所有Action 
    与result作用范围类似,先局部,再全局

    六、过滤器与拦截器

    1.过滤器Filter 
    过滤器Filter是Servlet中较为实用的一种技术,允许Servlet对用户请求进行预处理,并对Servlet响应进行后续处理. 
    在Struts2中,其核心控制器StrutsPrepareAndExecuteFilter就是一个过滤器,用来对用户请求进行预处理以及后处理 
    参考详谈Filter过滤器

    2.拦截器Interceptor 
    和过滤器类似,拦截器用于在Action被调用之前对请求进行预处理,以及Action被调用后进行后续处理 
    参考Struts2拦截器 
    此外,众多默认拦截器的用法可参考拦截器详解

    3.案例:Struts2权限验证功能的过滤器实现与拦截器实现 
    Struts2 角色权限

    七、Struts2标签库与OGNL表达式

    在JSP中,为了减少JSP中嵌入大量的Java代码,JSP规范制定了JSP标准标签库JSTL(JSP Standard Tag Library),提高了JSP页面的可读性和可维护性。 
    而Struts2也有自己独特的标签库,而且更为强大,不仅可以替代JSTL标签库,还适用于任何表示层技术(如Velocity、FreeMarker等)

    解压Struts2提供的struts2-core-x.x.x.jar文件,可以在META-INF目录下找到struts2标签库描述文件struts-tags.tld 
    在JSP中使用标签库时,需要使用taglib指令引入标签库

    <%@ taglib prefix="s" uri="/struts-tags" %>
    • 1

    其中prefix=”s” 指定了标签库的前缀,uri=”/struts-tags”指定了标签库描述文件的路径。 
    如果Sevlet规范版本是2.3及以下,还需要在web.xml中增加对标签库的定义

    <taglib>
        <taglib-uri>/struts-tags</taglib-uri>
        <taglib-location>/WEB-INF/lib/**struts2-core-2.0.11.1.jar**</taglib-location>
    </taglib>
  • 相关阅读:
    基于HTML5的多张图片上传
    如何限制textarea文本框的输入字数
    页面第一次加载实现图片淡入方式加载
    ajax实现的无刷新分页代码实例
    26个Jquery使用小技巧
    Windows下搭建PHP开发环境
    Jquery插件之ajaxForm ajaxSubmit的理解用法
    Java XML解析器
    JS截取字符串
    在Eclipse中配置tomcat
  • 原文地址:https://www.cnblogs.com/wxj-106/p/8127418.html
Copyright © 2011-2022 走看看