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>
- @Controller
- public class TestController {
- @RequestMapping("/test.html")
- public ModelAndView handleRequest(){
- System.out.println("---------TestController executed--------");
- return new ModelAndView("test");
- }
- }
- <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
如有其它更好建议或者不同意见欢迎留言或者入群探讨: