1.过滤器
过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上。它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。
作用
请求和回应的过滤,传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者struts的action前统一设置字符集,或者去除掉一些非法字符(聊天室经常用到的,一些骂人的话)。
Servlet过滤器的基本原理
在请求进入容器之后,还未进入Servlet之前进行预处理;在请求结束返回给前端之前进行后期处理。处理完成后,它会交给下一个过滤器处理,直到请求发送到目标为止。
2.拦截器
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。比如日志,安全等。
拦截器链,就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
一般拦截器方法都是通过动态代理的方式实现。
作用
比如通过它来进行权限验证,或者判断用户是否登陆,或者是像12306 判断当前时间是否是购票时间。
3.区别
①拦截器是基于动态代理的,属于面向切面编程(AOP)的一种运用;而过滤器是基于函数回调。
②拦截器不依赖于servlet容器,通过动态代理实现;过滤器依赖于servlet容器。
③拦截器可以在方法前后,异常前后等多次调用,而过滤器只能在某一次请求前和请求后各调用一次。
④过滤器几乎可以过滤所有的请求,包括页面、图片、js等静态资源以及请求;而拦截器只能对一些action或者controller进行拦截。
⑤拦截器可以利用依赖注入,而过滤器则不能直接注入(原因详情见:http://blog.csdn.net/qq_39470733)因此在Spring框架程序中,优先拦截器。
4.如果在一个项目中仅仅只有一个拦截器或者过滤器,那么我相信相对来说理解起来是比较容易的。但是我们是否思考过:如果一个项目中有多个拦截器或者过滤器,那么它们的执行顺序应该是什么样的?或者再复杂点,一个项目中既有多个拦截器,又有多个过滤器,这时它们的执行顺序又是什么样的呢?
public class TestFilter1 extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//在DispatcherServlet之前执行
<a target="_blank" href="http://www.07net01.com/tags-system-0.html" class="infotextkey" style="background:transparent; color:rgb(66,139,202)">system</a>.out.println("############TestFilter1 doFilterInternal executed############");
filterChain.doFilter(request, response);
//在视图页面返回给<a target="_blank" href="http://www.07net01.com/tags-%E5%AE%A2%E6%88%B7%E7%AB%AF-0.html" class="infotextkey" style="background:transparent; color:rgb(66,139,202)">客户端</a>之前执行,但是执行顺序在Interceptor之后
System.out.println("############TestFilter1 doFilter after############");
}
}
②filter过滤器 2
public class TestFilter2 extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println("############TestFilter2 doFilterInternal executed############");
filterChain.doFilter(request, response);
System.out.println("############TestFilter2 doFilter after############");
}
}
③在web.xml中注册这两个过滤器
<!-- 自定义过滤器:testFilter1 -->
<filter>
<filter-name>testFilter1</filter-name>
<filter-class>cn.zifangsky.filter.TestFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>testFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 自定义过滤器:testFilter2 -->
<filter>
<filter-name>testFilter2</filter-name>
<filter-class>cn.zifangsky.filter.TestFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>testFilter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(2)再定义两个拦截器:
①拦截器 1
public class BaseInterceptor implements HandlerInterceptor{
/**
* 在DispatcherServlet之前执行
* */
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("************BaseInterceptor preHandle executed**********");
return true;
}
/**
* 在controller执行之后的DispatcherServlet之后执行
* */
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("************BaseInterceptor postHandle executed**********");
}
/**
* 在页面渲染完成返回给客户端之前执行
* */
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("************BaseInterceptor afterCompletion executed**********");
// Thread.sleep(10000);
}
}
②拦截器 2
public class TestInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
System.out.println("************TestInterceptor preHandle executed**********");
return true;
}
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("************TestInterceptor postHandle executed**********");
}
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("************TestInterceptor afterCompletion executed**********");
}
}
③在SpringMVC配置文件中配置拦截器
<!-- 拦截器 -->
nbsp; <mvc:interceptors>
<!-- 对所有请求都拦截,公共拦截器可以有多个 -->
<bean name="baseInterceptor" class="cn.zifangsky.interceptor.BaseInterceptor" />
<!-- <bean name="testInterceptor" class="cn.zifangsky.interceptor.TestInterceptor" /> -->
<mvc:interceptor>
<!-- 对/test.html进行拦截 -->
<mvc:mapping path="/test.html"/>
<!-- 特定请求的拦截器只能有一个 -->
<bean class="cn.zifangsky.interceptor.TestInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
(3)定义一个测试controller:
@Controller
public class TestController {
@RequestMapping("/test.html")
public ModelAndView handleRequest(){
System.out.println("---------TestController executed--------");
return new ModelAndView("test");
}
}
(4)定义一个测试页面:
<body>
<%
System.out.println("test.jsp is loading");
%>
<div align="center">
This is test page
</div>
</body>
(5)测试效果:
①单独访问filter的测试请求 http://localhost:8080/FilterDemo
这就说明过滤器的运行是依赖于servlet容器的,跟springmvc等框架并没有关系。并且,多个过滤器的执行顺序跟xml文件中定义的先后关系有关
②接着清空控制台中的输出内容并访问:http://localhost:8080/FilterDemo/test.html
相信从这个打印输出,大家就可以很清晰地看到有多个拦截器和过滤器存在时的整个执行顺序了。当然,对于过个拦截器它们之间的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关
如有披露或问题欢迎留言或者入群探讨