**Java 拦截器和过滤器(转)**

来源:互联网 发布:html5数据统计 编辑:程序博客网 时间:2024/05/01 21:30
  • 理解Struts2拦截器

    1.Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.

    2.拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

  • 实现Struts2拦截器原理

    Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器

  • 定义Struts2拦截器

Struts2规定用户自定义拦截器必须实现com.opensymphony.xwork2.interceptor.Interceptor接口。

该接口声明了3个方法:

void init(); void destroy(); String intercept(ActionInvocation invocation) throws Exception;

其中,init和destroy方法会在程序开始和结束时各执行一遍,不管使用了该拦截器与否,只要在struts.xml中声明了该Struts2拦截器就会被执行。
intercept方法就是拦截的主体了,每次拦截器生效时都会执行其中的逻辑。

不过,struts中又提供了几个抽象类来简化这一步骤。

public abstract class AbstractInterceptor implements Interceptor;public abstract class MethodFilterInterceptor extends AbstractInterceptor;

都是模板方法实现的。

其中AbstractInterceptor提供了init()和destroy()的空实现,使用时只需要覆盖intercept()方法;

而MethodFilterInterceptor则提供了includeMethods和excludeMethods两个属性,用来过滤执行该过滤器的action的方法。可以通过param来加入或者排除需要过滤的方法。

一般来说,拦截器的写法都差不多。看下面的示例:

package interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.Interceptor;public class MyInterceptor implements Interceptor {public void destroy() {}public void init() {}public String intercept(ActionInvocation invocation) throws Exception {System.out.println("Action执行前插入 代码");      //执行目标方法 (调用下一个拦截器, 或执行Action)    final String res = invocation.invoke();    System.out.println("Action执行后插入 代码");    return res;      }}
  • 配置Struts2拦截器

Struts2拦截器需要在struts.xml中声明,如下struts.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN""http://struts.apache.org/dtds/struts-2.0.dtd"><struts><constant name="struts.objectFactory" value="spring" /><package name="default" extends="struts-default"> <interceptors> <interceptor name="MyInterceptor" class="interceptor.MyInterceptor"></interceptor> <interceptor-stack name="myInterceptorStack"> <interceptor-ref name="MyInterceptor"/><interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <action name="loginAction" class="loginAction"> <result name="fail">/index.jsp </result> <result name="success">/success.jsp</result> <interceptor-ref name="myInterceptorStack"></interceptor-ref> </action> </package> </struts>
  • 过滤器

过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者struts的action前统一设置字符集,或者去除掉一些非法字符

  • 拦截器

拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

  • 拦截器与过滤器的区别 :

-拦截器是基于java的反射机制的,而过滤器是基于函数回调。
-拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
-拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
-拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
-在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

  • 执行顺序 :

过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。
个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。

一个Filter 可负责拦截多个请求或响应:一个请求或响应也可被多个请求拦截。

创建一个Filter 只需两个步骤:
(1)创建Filter 处理类:

(2)在web.xml 文件中配置Filter 。

创建Filter 必须实现javax.servlet.Filter 接口,在该接口中定义了三个方法。

// 用于完成Filter 的初始化。 void init(FilterConfig config);// 用于Filter 销毁前,完成某些资源的回收。 void destroy(); //实现过滤功能,该方法就是对每个请求及响应增加的额外处理。void doFilter(ServletRequest request, ServletResponse response,FilterChain chain);
  • 过滤器Filter生命周期:

init()->doFilter()->destroy(),由部署文件中的filter元素驱动。在servlet2.4中,过滤器同样可以用于请求分派器,但须在web.xml中声明,INCLUDE或FORWARD或REQUEST或ERROR该元素位于filter-mapping中。

  • Filter常用的场景:

例一、 日志的记录,当有请求到达时,在该过滤器中进行日志的记录。处理完成后,进入后续的Filter或者处理。

步骤1:编写Filter类

package test.filter;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletContext;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest; public class LogFilter implements Filter {private FilterConfig config;// 实现初始化方法public void init(FilterConfig config) {this.config = config;}// 实现销毁方法public void destroy() {this.config = null;}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) {// 获取ServletContext 对象,用于记录日志ServletContext context = this.config.getServletContext();long before = System.currentTimeMillis();System.out.println("开始过滤... ");// 将请求转换成HttpServletRequest 请求HttpServletRequest hrequest = (HttpServletRequest) request;// 记录日志context.log("Filter已经截获到用户的请求的地址: " + hrequest.getServletPath());try {// Filter 只是链式处理,请求依然转发到目的地址。chain.doFilter(request, response);} catch (Exception e) {e.printStackTrace();}long after = System.currentTimeMillis();// 记录日志context.log("过滤结束");// 再次记录日志context.log(" 请求被定位到" + ((HttpServletRequest) request).getRequestURI()+ "所花的时间为: " + (after - before));}}

在上面的请求Filter中,仅在日志中记录请求的URL,对所有的请求都执行chain.doFilter(request,reponse)方法,当Filter 对请求过滤后,依然将请求发送到目的地址。

步骤2:在web.xml中配置Filter

<!-- 定义Filter --><filter><!-- Filter 的名字 --><filter-name>log</filter-name><!-- Filter 的实现类 --><filter-class> test.filter.LogFilter</filter-class></filter><!-- 定义Filter 拦截地址 --><filter-mapping><!-- Filter 的名字 --><filter-name>log</filter-name><!-- Filter 负责拦截的URL --><url-pattern>/filter/*</url-pattern></filter-mapping>

参考来源:>http://www.cnblogs.com/wangyuyu/archive/2013/07/02/3167354.html

0 0
原创粉丝点击