struts2框架学习(四)——拦截器

一、struts2拦截器

1、什么是拦截器:

  拦截器是一种可以让用户在Action执行之前和Result执行之后进行一些处理的机制;而且它在Action执行之前和Result执行之后所走的顺序是相反的。

2、拦截器vs过滤器:

  过滤器是servlet规范中的技术,可以对请求进行响应,比如我们可以在在传入的HttpServletRequest、HttpServletResponse提前过滤一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url,或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符;

  过滤器是struts2框架中的技术,他实现的是一种AOP的编程思想,是可插拔的,可以对访问某个 Action 方法之前或之后实施拦截。 

  拦截器与过滤器的区别 :

(1) 拦截器是基于java的反射机制的,而过滤器是基于函数回调。

(2)拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

(3)拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

(4)拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

(5)在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

3、拦截器的优点

(1) 简化Action的实现,拦截器能把很多功能从Action中独立出来,这大量减少了Action的代码,而且使得Action功能更加的单一;

(2) 实现通用代码模块化,将这些从Action中分离除去的功能,放到拦截器中去实现,这样可以将多个Action通用的代码放在一个或者多个拦截器中进行承装即可。

(3) 提高了重用性,当我们把通用的功能封装在拦截器中后,就可以针对不同的Action配置相应的拦截器了。

(4) 实现了AOP,struts2通过拦截器实现了AOP,他是一种编程范式,是一种分散实现关注功能的编程方法。

 

二、自定义拦截器

1、Intercepter:

  struts2定义了一个拦截器接口Intercepter接口,它里面有三个方法。

  (1) init:该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化;

  (2) interecept: 每拦截一个动作请求, 该方法就会被调用一次;

  (3) destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也只被调用一次。

2、ActionIntercepter:

Struts 会依次调用程序员为某个 Action 而注册的每一个拦截器的 interecept 方法.每次调用 interecept 方法时, Struts 会传递一个 ActionInvocation 接口的实例。ActionInvocation 代表一个给定动作的执行状态, 拦截器可以从该类的对象里获得与该动作相关联的 Action 对象和 Result 对象. 在完成拦截器自己的任务之后, 拦截器将调用 ActionInvocation 对象的 invoke 方法前进到 Action 处理流程的下一个环节。

3、步骤:

 1、 写一个类,该类继承import com.opensymphony.xwork2.interceptor.Interceptor接口;

public class LoginInterceptor implements Interceptor{

    private static final long serialVersionUID = 6202373684245243844L;

    public void destroy() {
    }

    public void init() {
    }

    
    /**
     * 这个方法的返回值的作用参考 Action 的result标签的name值
     */
    public String intercept(ActionInvocation arg0) throws Exception {
        
        HttpSession session = ServletActionContext.getRequest().getSession();
        Emp emp = (Emp) session.getAttribute("emp");
        if( emp == null ){
            return "noLogin";
        }  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    
        String date = sdf.format(new Date());
        
        //得到将要调用的Action

        String result = arg0.invoke();
        System.out.println("雇员:"+ emp.getEmail() +"在"+ date +" 操作方法: "+ arg0.getInvocationContext().getName() );
        
        return result;
    }
}

2、 在struts.xml中进行定义。

  拦截器的配置:

    (1) 拦截器以name-class的形式配置在struts-default.xml中,name为拦截器的名字(拦截器的唯一标识),class指定该拦截器的实现类;

<interceptor name="拦截器的名字" class="拦截器的实现类">
    <param name="参数名">参数值</param>
</interceptor>

    (2) 拦截器在action中的配置;

<action name="deptlist" class="com.xullent.eec.action.DeptAction">
 <result name="success">dept/list.jsp</result>
 <interceptor-ref name="checkLogin" />
</action>

    (3)定义实现动作类:

package com.chinasoft.struts2.demo.action;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.chinasoft.struts2.demo.bean.Emp;
import com.opensymphony.xwork2.ModelDriven;

public class LoginAction implements ModelDriven<Emp> {
    
    //Emp类中的一个属性,称为属性驱动
    //    private String email;
    //模型驱动
    private Emp emp ;
    public String execute() throws Exception{
        HttpSession session = ServletActionContext.getRequest().getSession();
        session.setAttribute("emp", emp);
        return "success";
    }

    public Emp getEmp() {
        return emp;
    }

    public void setEmp(Emp emp) {
        this.emp = emp;
    }

    /**
     * 这个方法可以帮助我们减少页面name属性的长度和复杂度
     */
    public Emp getModel() {
        if( emp == null     ) emp = new Emp();
        return emp;
    }
}

里面的ModelDriven<T>接口,里面的getModel方法可以帮助我们减少页面name属性的长度和复杂度。

  拦截器栈:拦截器栈是由interceptor-stack 定义的,然后使用interceptor-ref 来引用已成在的拦截器,组成一个拦截器栈。它其实就是一个大的拦截器。和拦截器一样,它们都会在Action的execute方法之前自动执行;

  拦截器栈的配置:

<interceptors>
    <interceptor name="拦截器的名字" class="拦截器的实现类">
        <param name="参数名">参数值</param>
    </interceptor>
    <interceptor name="拦截器1" class="interceptor1"/>
    <interceptor name="拦截器2" class="interceptor2"/>
    <interceptor name="拦截器3" class="interceptor3"/>
    <interceptor name="拦截器4" class="interceptor4"/>
    
    <interceptor-stack name="拦截器栈1">
        <interceptor-ref name="拦截器1"/>
        <interceptor-ref name="拦截器2"/>
        <interceptor-ref name="拦截器3"/>
    </interceptor-stack>
    
    <interceptor-stack name="拦截器栈2">
        <interceptor-ref name="拦截器4"/>
        <interceptor-ref name="拦截器栈1"/>
    </interceptor-stack>
</interceptors>

拦截器完整的配置:

<package name="syxpj"  extends="struts-default" namespace="/syxpj">
    <interceptors>
        <interceptor name="拦截器的名字" class="拦截器的实现类">
            <param name="参数名">参数值</param>
        </interceptor>
        <interceptor name="拦截器1" class="interceptor1"/>
        <interceptor name="拦截器2" class="interceptor2"/>
        <interceptor name="拦截器3" class="interceptor3"/>
        <interceptor name="拦截器4" class="interceptor4">
            <param name="arg1">arg1</param>
        </interceptor>
        
        <interceptor-stack name="拦截器栈1">
            <interceptor-ref name="拦截器1"/>
            <interceptor-ref name="拦截器2"/>
            <interceptor-ref name="拦截器3"/>
        </interceptor-stack>
        
        <interceptor-stack name="拦截器栈2">
            <interceptor-ref name="拦截器4"/>
            <interceptor-ref name="拦截器栈1"/>
        </interceptor-stack>
    </interceptors>
    
    <action name="action1" class="class1">
        <result name="success">welcome.jsp</result>
        <result name="error">err.jsp</result>
        <!-- 使用系统默认的拦截器栈 -->
        <interceptor-ref name="defaultStack"/>
        <interceptor-ref name="拦截器栈2"/> 
        <interceptor-ref name="拦截器4">
            <param name="arg1">覆盖了默认参数</param>
        </interceptor-ref>
    </action>
</package>

 

posted @ 2017-01-17 16:24  xullent  阅读(162)  评论(0编辑  收藏  举报