一、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>