Struts2

Struts2

Struts2两个重要组成部分

struts2核心就是核心控制器和业务控制器。

核心控制器StrutsPrepareAndExecuteFilter

StrutsPrepareAndExecuteFilter作为一个filter运行在web应用中,负责拦截所有用户请求,该filter 会过滤用户请求,然后将请求都交给struts2框架处理。拦截器会默认拦截扩展名为.action的请求,什么后缀名都不写也可以。例如hello.action或者hello都会进行拦截。xxx.jsp就不会进行拦截,直接放行。 

(1)启动Tomcat,tomcat加载web.xml文件。同时加载和初始化核心过滤器,查看struts2源码,发现核心过滤器的初始化方法中会加载struts.xml等struts2配置文件。

(2)当用户请求到达时,核心过滤器拦截用户请求,将请求交给struts2框架来处理,即去匹配struts.xml的内容。
struts2框架获取用户请求后,根据请求的名字来决定调用哪个业务逻辑组件,实例化相应的类。例如,对于login请求,调用名为login的Action处理。

(3)struts2的所有Action都被定义在struts.xml文件中,Action有name和class属性,name决定了该Action处理哪个用户请求,class决定了该Action的实现类。

(4)Struts2用户处理用户请求的Action实例,并不是用户实现的业务控制器,而是Action代理,他会回调用户的处理方法,因为用户实现的业务控制器没有与Servlet API有任何关系,所以根本没办法进行获取参数等请求处理,而struts2定义了一系列拦截器,会对请求参数解析,传入到Action中,回调execute方法。

我们每次请求都会实例化相应的类,所以不会出现线程不安全的情况。而Servlet为单例,会出现线程不安全。

业务控制器:

业务控制器就是用户实现的Action类,Action类中通常包含一个execute方法,该方法返回一个字符串,字符串与struts.xml中的result的name相对应,跳转到不同页面。

struts2内部运行流程

struts2内部运行流程

(1)客户端发出HTTP请求

(2)然后请求被核心过滤器StrutsPrepareAndExecuteFilter拦截

(3)核心过滤器将请求转发到Action映射器,Action映射器负责识别当前的请求是否需要交由Struts2处理。

(4)Action映射器返回需要struts2处理的信息,StrutsPrepareAndExecuteFilter会创建一个Action代理

(5)Action代理并不知道执行哪一个Action,它会向配置管理器询问调用哪一个Action,配置管理器会从struts.xml读取我们配置的Action信息。

(6)Action代理创建相关请求的Action对象,调用相关的方法之前,struts2的一系列拦截器会帮我们做一些操作,例如获取请求参数等。

(7)然后调用execute方法根据返回的字符串去匹配相应的页面,

(8)页面可以获取一些页面模板,然后生成最终页面,再倒序的执行拦截器的后续操作

(9)最后生成HTTP响应内容

struts.xml文件中配置和修改常量

<package name="demo" extends="struts-default">
    <action name="hello" class="com.cad.struts2.Hello" method="sayHello">
        <result name="success">/welcome.jsp</result>
        <result name="error">/error.jsp</result>
    </action>
</package>  
//修改请求后缀为abc
<constant name="struts.action.extension" value="abc"></constant> 

 <body>
     //使用默认请求后缀
     <a href="${pageContext.request.contextPath }/hello.action">后缀为.action</a>
     <a href="${pageContext.request.contextPath }/hello">没有后缀</a>
     <a href="${pageContext.request.contextPath }/hello.abc">后缀为.abc</a>
</body>

在web.xml文件中配置常量

//修改请求后缀为do
<init-param>
    <param-name>struts.action.extension</param-name>
    <param-value>do</param-value>
</init-param>

package包配置

    struts2框架的核心组件就是Action,拦截器等。struts2使用包来管理Action,拦截器等。 

            属性
            name:配置包时,必须指定name属性,是包的唯一标识。  

            extends:属性值必须是另一个包的name属性。指定extends属性表示继承其他包。子包可以集成一个或多个父包中的拦截器,拦截器栈,action等配置。 

            例如我们前面项目中定义的 <package name="demo" extends="struts-default"> ,就继承struts-default.xml中的struts-default包。 

            abstract:可选属性。指定该包是否是抽象包,抽象包不能包含Action定义。

            namespace:该属性是一个可选属性,定义该包的命名空间。一个web应用中可能出现同名Action。同一个命名空间中不能有同名Action 

            某个包指定命名空间后,该包下的所有action的url地址必须是 命名空间+action 

            例如我们加一个命名空间,则访问这个动作的时候必须加上命名空间。例如 http://localhost:8080/Struts2Demo/user/hello.action 

            <package name="demo" extends="struts-default" namespace="/user">
                <action name="hello" class="com.cad.struts2.Hello" method="sayHello">
                    <result name="success">/welcome.jsp</result>
                    <result name="error">/error.jsp</result>
                </action>
            </package>  

            如果包没有指定命名空间,则默认的命名空间为""  
            根命名空间为"/" 

Action

第一种创建处理类方法

    struts2采用了低侵入式的设计,struts2不要求Action类继承任何的struts基类,也不需要实现任何接口。Action类只是一个普通的POJO(Plain Ordinary Java Object简单的java对象) 
1

第二种:创建一个类实现Action接口,该接口定义了五个字符串常量。还包含一个String execute()方法

            public interface Action{
                五个字符串常量
                public static final String  ERROR="errror";
                public static final String  INPUT="input";
                public static final String  LOGIN="login";
                public static final String  NONE="none";
                public static final String  SUCCESS="success"; 
                //处理用户请求的execute方法
                    public String execute()throws Exception;
            }    

第三种:继承Action接口的实现类ActionSupport,该类提供了很多的默认方法,包括获取国际化信息,数据校验的方法等。大大简化了Action的开发。我们开发中选择第三种

配置Action

        在struts.xml文件中配置。struts2使用包来组织action。所以action定义放在包定义的下面 。<action.../>
            属性
                name:action的名字
                class:指定该action的实现类,class属性并不是必须的,如果我们不指定class属性,系统默认使用ActionSupport类 
        配置Action的默认处理类
            如果我们不指定<action>中的class属性,默认使用ActionSupport类。
            我们可以使用<default-class-ref class=""></default-class-ref>来指定默认的动作处理类。  

Action的方法调用

我们继承的ActionSupport,当我们执行Action的时候,默认执行他的execute方法,现在我们来执行自己的方法。< action >中有一个method属性,可以指定用户调用哪个方法。

<action name="addUser" class="com.cad.struts2.Hello" method="addUser">
                            <result name="success">/welcome.jsp</result>
                            <result name="error">/error.jsp</result>
                </action> 

这种方式写的很多代码类似,相当冗余,为了解决这个问题,struts2提供了通配符的配置方式帮我们解决这个问题。

<action name="*" class="com.cad.struts2.Hello" method="{1}">
                            <result name="success">/{1}.jsp</result>
                            <result name="error">/error.jsp</result>
                        </action>

action的name中可以使用通配符 * , * 可以匹配所有的action, * 的值为传入的action名字,例如传入了addUser.action,那么 * 的值就为addUser。method属性中可以使用表达式来获取 * 的值,{第几个*}

例如 ” * _ * “,我们传递add_User,那么{1}的值就是add,{2}的值就是User。

动态方法调用

使用动态调用前要先将动态调用的常量更改成true,动态调用默认是false,因为不安全。 
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>

<action name="user" class="com.cad.struts2.Hello" >
            <result name="success">/welcome.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
//jsp
<body>
    <a href="${pageContext.request.contextPath }/user!addUser">添加用户</a>
    <a href="${pageContext.request.contextPath }/user!updateUser">修改用户</a>
    <a href="${pageContext.request.contextPath }/user!selectUser">查看用户</a>
    <a href="${pageContext.request.contextPath }/user!deleteUser">删除用户</a>
</body>

结果类型

<result../>属性 
            name:逻辑视图名称,应该与Action返回的字符串相同,如果不填写,默认为success
            type:结果视图类型,不写的时候默认值为dispatcher(请求转发)
            name是去哪里,type是怎么去。 
1234

struts内建支持的常用结果类型

    -chain:Action链式处理。当一个Action处理完成之后,系统并不想转发到视图资源,而是希望下一个Action进行处理,此时就需要这个类型。  

    -dispatcher:请求转发 

    -redirect:重定向 

    -redirectAction:重定向到其他Action 

    -stream:向浏览器返回一个InputStream的结果类型(一般用于文件下载) 

Action访问Servlet API

第一种方式

    Struts2提供了一个ServletActionContext对象可以访问ServletAPI。
例如
    HttpServletRequest request=ServletActionContext.getRequest();
    HttpServletResponse response=ServletActionContext.getResponse();
    ServletContext context=ServletActionContext.getServletContext();
    HttpSession session=request.getSession(); 

第二种方式,实现ServletContextAware,ServletRequestAware,ServletResponseAware三个接口 
public class VcodeAction extends ActionSupport implements ServletContextAware,ServletRequestAware,ServletResponseAware { 
                    //定义三个参数
                    private HttpServletRequest request;
                    private HttpServletResponse response;
                    private ServletContext context;

                    public String execute() throws Exception {

                        return null;
                    } 
                    //实现接口中设置参数的方法
                    @Override
                    public void setServletResponse(HttpServletResponse response) {
                        this.response=response;

                    }
                    @Override
                    public void setServletRequest(HttpServletRequest request) {
                        this.request=request;

                    }
                    @Override
                    public void setServletContext(ServletContext context) {
                        this.context=context;

                    }
                }             

执行流程是什么,谁调用了set方法?

  1. struts的内建拦截器有一个ServletConfig的拦截器。它会先得到我们的动作类的引用,
  2. 然后通过instanceof方法判断我们动作类是否属于ServletContextAware,ServletRequestAware,ServletResponseAware类型, 因为我们实现了这个接口,当然属于这个类型
  3. 然后获取request,response等,调用我们动作类实现的接口方法 setServletResponse,setServletRequest,setServletContext等为我们的request,response赋值

分文件编写配置文件

 <struts>
     <include file="struts-user.xml"/>
     <include file="struts-order.xml"/>
     .......
</struts>

模型驱动和属性驱动

出于结构清晰的考虑,应该采用单独的Model实例来封装请求参数和处理结果,这就是所谓的模型驱动, 

 所谓模型驱动,就是使用单独的JavaBean来贯穿整个MVC流程。 

 所谓属性驱动,就是使用属性来作为贯穿MVC流程的信息携带者,当然属性必须依附于对象,这个对象就是Action实例。 

 简单说,模型驱动就是使用单独的javaBean封装请求参数。
        属性驱动就是把属性写在Action类中。 
public class AdduserAction extends ActionSupport {
                    private User user;
}
<body>
    <form action="${pageContext.request.contextPath }/action1" method="post">
    用户名:<input type="text" name="user.username"><br>
    年 龄:<input type="text" name="user.age"><br>
        <input type="submit" value="提交">
        </form>
        </body>

我们发现上面的jsp中的name必须前面得加 user.username。太过麻烦。我们使用模型驱动来解决这个问题。实际开发中使用这种方式

              我们改进动作类 

public class AdduserAction extends ActionSupport implements ModelDriven<User>{
                    //数据模型对象由我们实例化
                    private User user=new User();

                    public User getUser() {
                        System.out.println("getuser");
                        return user;
                    }

                    public void setUser(User user) { 
                        System.out.println("setuser");
                        this.user = user;
                    }
                    public String adduser(){ 
                        System.out.println(user.getUsername()+":"+user.getAge());
                        return null;
                    }
                    //实现接口方法,返回我们的数据模型对象
                    public User getModel() {
                        // TODO Auto-generated method stub
                        return user;
                    }

                } 12345678910111213141516171819202122232425262728293031
        我们在jsp上就能像以前那样 ,name只用我们的参数相同即可 

        <body>
            <form action="${pageContext.request.contextPath }/action1" method="post">
                用户名:<input type="text" name="username"><br>
                年 龄:<input type="text" name="age"><br>
                <input type="submit" value="提交">
            </form>
        </body>

模型驱动的要求:
1.动作类实现ModelDriven接口
2.实现接口中的getModel方法,返回我们的数据对象
3.数据模型对象必须由我们实例化。

原理:

    其实这时候表单的name已经不仅仅是一个简单的字符串了。 

    这一系列的操作是由ModelDriven和params拦截器帮我们做的 。 

    params拦截器负责提取请求参数,如果是属性驱动模式,则还负责将请求参数传给Action类的属性 

    模型驱动的话就只提取请求参数。 

    ModelDriven拦截器会先判断我们的动作类是否属于ModelDriven类型  

    属于的话,就调用我们实现的getModel方法,获取我们传入的对象 

    然后将我们的对象给压入栈中  

struts2的异常处理机制

我们看Action接口中的execute方法声明。
    public String execute() throws Exception 

    这就意味着我们重写该方法时,无需进行任何异常处理,而是把异常抛给struts2框架处理. 

    struts2框架接收到Action抛出的异常后,根据struts.xml文件配置的异常映射,转入指定的视图资源。

    异常映射功能是由 exception的拦截器帮我们做的。

    struts2的异常处理机制是通过在struts.xml中配置<exception-mapping..../>元素完成。
        属性:
            exception:异常类型
            result:出现该异常时,系统转入result指定的结果 

局部异常映射和全局异常映射

全局异常映射对所有的Action都有效,但局部异常映射只对该异常映射所在的Action有效。
如果全局异常映射和局部异常映射配置了同一个异常类型,在该Action内,局部覆盖全局。

局部异常映射:将<exception-mapping..../>元素作为<action.../>的子元素配置 

全局异常映射:将<exception-mapping..../>元素作为<global-exception-mappings>元素的子元素配置 

struts2的未知处理器

从struts2.1开始,struts2增加了未知处理器。  

当用户请求未知Action,或指定Action里的未知方法,或Action处理结束后返回一个未知的result。struts2允许使用未知处理器来处理这些情况。

未知处理器需要实现UnknownHandler接口,该接口包含三个方法 

-handleUnknownAction:用户请求未知Action时,该方法会被回调
-handleUnknownActionMethod:用户请求指定Action的未知方法时,该方法会被回调
-handleUnknownResult:Action处理结束后返回一个未知Result时,该方法会被回调 

一旦实现了自定义的未知处理器,就可以在struts.xml中通过<bean../>元素来配置未知处理器
例如 
<bean name="myHandler" class="com.cad.struts2.MyUnknownHandler" type="com.opensymphony.xwork2.UnknownHandler"></bean> 
12345678910111213

未知处理器案例

        第一步:我们实现我们简单的未知处理器

            public class MyUnknownHandler implements UnknownHandler {

                public ActionConfig handleUnknownAction(String namespace, String actionName) throws XWorkException {
                    System.out.println(actionName+"不存在");
                    return null;
                }


                public Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig,
                        String resultCode) throws XWorkException {
                    System.out.println(resultCode+"不存在");
                    return null;
                }


                public Object handleUnknownActionMethod(Object action, String methodName) throws NoSuchMethodException {
                    System.out.println(methodName+"不存在");
                    return null;
                }

            }
            第二步:在struts.xml中配置未知处理器 

            //定义我们的未知处理器
            <bean name="myHandler" class="com.cad.struts2.MyUnknownHandler" type="com.opensymphony.xwork2.UnknownHandler"></bean>

            <package name="p3" extends="struts-default">
                <action name="myAction"></action>
            </package> 
            //定义未知处理器栈
            <unknown-handler-stack>
                <unknown-handler-ref name="myHandler"></unknown-handler-ref>
            </unknown-handler-stack> 123456789101112
然后我们访问myAction,会输出success不存在。
是因为不指定action的class属性时,默认使用ActioSupport
一般未知处理器主要处理Action返回未知result时有用。
了解即可。 

struts2的类型转换

Struts2内建的类型转换器

struts内建的类型转换器能自动将我们的表单数据(字符串)转换成对应的数据类型。

完成字符串和日期类型之间的转换时,日期格式必须使用请求用户本地的格式。一般是yyyy-MM-dd,如果输入的日期格式不是本地的日期格式,例如我们输入1996/01/31,就会出现错误,类型转换失败。

自定义类型转换器

当我们在表单中输入的日期格式不是本地的格式时,就会出现类型转换错误,我们也经常需要将字符串转换成其他的格式,例如字符串转换成对象之类的操作,这时我们就需要自定义类型转换器。

struts2的类型转换器实际上是基于OGNL实现的。xwork集成了OGNL。

实现类型转换器必须实现TypeConverter接口。这个接口的方法太过复杂,所以还提供了一个该接口的实现类DefaultTypeConverter。

我们重写DefaultTypeConverter类的convertValue方法即可。

我们基于DefaultTypeConverter类实现类型转换器时,将字符串转换成我们需要的类型通过convertValue方法实现,将我们的类型转换成字符串也是通过convertValue方法实现,因此我们必须判断转换的类型来实现不同的逻辑。

为了简化类型转换器的实现,struts2提供了一个StrutsTypeConverter抽象类,这个类是DefaultTypeConverter类的子类。

自定义类型转换器案例

需求:我们将我们前面的注册案例中的生日改成  yyyy/MM/dd类型  

第一步:创建自定义类型转换器 
        public class MyConverter extends StrutsTypeConverter { 
                    //日期转换器,转换成指定的类型
                    private DateFormat format=new SimpleDateFormat("yyyy/MM/dd");

                    //将字符串转换成日期类型
                    public Object convertFromString(Map context, String[] values, Class toClass) { 
                        //判断参数是否为空
                        if(values==null||values.length==0){
                            return null;
                        } 
                        //我们只有一个参数,就是表单的birthday
                        String date=values[0]; 
                        //判断目标类型是否是Date
                        if(toClass==java.util.Date.class){
                            try { 
                                //进行转换
                                return format.parse(date);
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }
                        return null;    
                    }


                    //将日期类型转换成字符串
                    public String convertToString(Map context, Object o) { 
                        //判断当前参数是否是日期类型
                        if(o instanceof java.util.Date){
                            return format.format(o);
                        }
                        return null;
                    }
                }
                
第二步:注册类型转换器
局部类型转换器
        按照属性来注册
        如果属性都在action中,那么应该创建一个文件 Action名字-conversion.properties ,例如LoginAction-conversion.properties 
        如果属性放到了javaBean中,那么创建一个文件 javaBean名称-conversion.properties 例如  User-conversion.properties

        文件由键值对组成。
        键为需要转换的属性名字,值为自己实现的类型转换器全类名。

        我们创建 User-conversion.properties 

        内容 birthday=com.cad.web.convert.MyConverter 

        这时我们注册时使用 1996/01/24这种格式进行注册就不会出现类型转换错误。
        用户提交请求时,请求中的birthday参数会先被该类型转换器处理。

全局类型转换器
        所有的Action都能用。我们需要在src目录下创建一个 xwork-conversion.properties 的文件

        因为是全局的,就不存在只对birthday这个属性进行转换。
        这里的键是要转换的类型,值还是类型转换器类。

        我们创建 xwork-conversion.properties 
        内容 java.util.Date=com.cad.web.convert.MyConverter 
        这样当我们输入日期的表单时,就可以使用我们自定义的日期格式。

struts2的输入校验

校验规则文件与Action类放在同一目录下

校验配置文件名称为 ActionClassName-validation.xml 例如 :UserAction-validation.xml

增加校验文件后,系统会自动加载该文件。当用户提交请求时,struts2会根据该文件对用户数据进行校验

基于表单字段的配置风格

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE validators PUBLIC
            "-//Apache Struts//XWork Validator 1.0.3//EN"
            "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> 
    //校验文件的根元素      
    <validators>
        //被校验表单项名称
        <field name="username"> 
            //指定校验器,struts2有很多内建校验器,requiredstring是校验数据是否为空并去除两端空格
            <field-validator type="requiredstring"> 
                //校验失败后的提示信息
                <message>用户名不能为空</message>
            </field-validator>
        </field>
    </validators>

校验失败后,struts2会返回名为input的逻辑视图名,因此我们还需要添加一个<result>   

这个配置文件是全局验证。也就是这个Action中的所有动作都会被验证,我们Action有的方法并不需要验证,加入验证甚至会出错。 

    我们有两种方式可以让不需要验证的方法跳过验证: 

    第一种:在不需要验证的方法前面添加注解@SkipValidation  

    第二种:针对动作类中的某个方法进行验证,创建的XML文件名为 ActionClassName-ActionName-validation.xml ,这里的ActionName不是方法名,而是配置的action名字 ,例如 :UserAction-regist-validation.xml 

非字段配置风格(基于验证器的配置风格)

<validators> 
    //验证器类型
    <validator type="requiredstring">
    //要校验的参数名字
    <param name="fieldName">password</param>
    //校验失败后返回的信息
    <message>密码不能为空</message>
    </validator>
</validators>

短路校验器

校验配置文件的<field-validator>和<validator>元素可以指定一个可选的short-circuit属性,指定该校验器是否是短路校验器,默认是false。 

    短路校验器的作用是如果一个字段内有多个校验器,如果一个校验器校验失败,其他校验器根本不会继续校验。

    校验器的执行顺序
        -所有基于验证器的配置风格的校验器优先于字段风格的校验器
        -所有的基于验证器风格的校验器,排在前面的先执行 
        -所有的基于字段风格的校验器,排在前面的先执行。 

    校验器的短路原则
        -所有的非字段校验器最先执行,如果某个非字段校验器校验失败,则该字段上的所有字段校验器都不会执行
        -非字段校验器校验失败,不会阻止其他非字段校验器的执行
        -如果某个字段校验器校验失败,则该字段下的后面的字段校验器都不会执行
        -字段校验器永远都不会阻止非字段校验器的执行 

struts2的内建校验器

            required:必填验证器,要求指定的字段必须有值。使用非字段风格的配置时,可以配置fieldName属性来设置要校验的表单项名称。 

            requiredstring:必填字符串验证器。 

            int、long、short:整数校验器。要求字段的整数值必须在指定范围内。参数:min指定该属性最小值,不指定不检查最小值。max指定该属性最大值,不指定不检查最大值。 

            date:日期校验器。要求字段的日期值必须在指定范围内。参数:min最小日期 ,max最大日期 

            expression:表达式校验器,它只能被非字段风格配置。参数:expression指定一个逻辑表达式。 

            fieldexpression:字段表达式校验器。要求字段满足一个逻辑表达式。 

            email:邮件校验器。要求被检查字段非空,并且必须是合法的邮箱地址,底层是正则表达式。 

            url:网址校验器。要求被检查字段非空并且是个发的url地址,底层是正则表达式。 

            stringlength:字符串长度校验器。要求字段长度必须在指定的范围内。参数:manLength 最大长度  minLength最小长度 

            regex:正则表达式校验器。
            等等。 

自定义校验

struts2内建的校验器可以完成大部分输入校验。但是有时候无法满足一些特殊的要求,struts2允许通过手动方式完成自定义校验。 


        继承ActionSupport,重写validate方法
            public void validate() {
                if(user.getUsername()==null||user.getUsername().isEmpty()){
                    addFieldError("username", "用户名不能为空!!!");
                }
            } 

        重写validate方法会检验action类里的所有方法,我们不需要校验某些方法,有两种方法。 

        第一种:在不需要校验的方法前加上注解@SkipValidation 
        第二种:重写validateXxx方法,Xxx即为要验证的方法名 
            public void validateRegist() {
                if(user.getUsername()==null||user.getUsername().isEmpty()){
                    addFieldError("username", "用户名不能为空!!!");
                }

            }

struts2的输入校验流程

1.对字符串类型的请求参数进行类型转换,并且设置给JavaBean的属性 

2.类型转换中可能出现异常,如果出现异常,将异常信息保存并封装 

3.调用struts2的输入校验规则进行输入校验(根据各种vatidate.xml文件里定义的校验规则) 

4.通过反射调用validateXxx方法进行校验  

5.调用validate方法校验 

6.上面的校验出现错误,转到input对应的视图资源。没错误,调用action中的处理方法。

struts2中的拦截器

拦截器体系是struts2重要的组成部分。正是大量的内建拦截器完成了该框架的大部分操作。    

struts2内建了大量的拦截器。这些拦截器配置在struts-default.xml中。       

struts2拦截器非常灵活,struts2允许使用各种拦截器,如果有一批拦截器需要经常使用,可以将这批拦截器组成拦截器栈。      struts2有一些通用功能是所有Action必需的,所以struts2将这些拦截器组成拦截器栈,并配置成默认的拦截器应用,大部分时候,我们直接使用defaultStack默认的拦截器栈即可。 

比如params拦截器将请求参数解析出来,设置Action的属性。servletConfig拦截器负责将request和response对象传给Action的等等     拦截器可以动态的拦截发送到指定Action的请求,通过拦截器机制,我们可以在Action执行的前后插入某些代码。    通过这种方式,就可以把多个Action中重复的代码提取出来,放在拦截器中,从而提高更好的代码复用性。     

理解DRY规则            

DRY:Don‘t Repeat Yourself 意思是不要书写重复的代码。

拦截器的使用

            在struts.xml中定义拦截器 

            <interceptor name="拦截器名" class="拦截器类" />

            如果配置拦截器时需要传入拦截器参数,则需要使用param元素。

            <interceptor name="拦截器名" class="拦截器类" > 
                <param name="参数名">参数值</param>
                ....
            </interceptor> 


            还可以把多个拦截器组成拦截器栈 
            <interceptor-stack name="拦截器栈名">
                <interceptor-ref name="拦截器一"/>
                <interceptor-ref name="拦截器二"/>
                ....
            </interceptor-stack>  

通过<intercept-ref name="拦截器名字" />使用拦截器

自定义拦截器

实现自定义拦截器需要实现Interceptor接口
            该接口有三个方法
            -void init():拦截器实例化之后调用,只会执行一次,用于初始化资源 

            -void destory():拦截器销毁之前调用 

            -String intercept(ActionInvocation invoction)throws Exception:该方法是用户需要实现的拦截动作。 该方法的ActionInvocation包含了被拦截的action引用等所有数据,可以调用该参数的invoke方法放行,如果有下一个拦截器转到下一个拦截器,如果没有就转给Action类的方法。

            struts2提供了AbstractInterceptor类实现了Interceptor接口,我们只需要继承这个类即可。  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值