Java_拦截器和过滤器的关系和区别

作者: 小疯子 分类: Java 发布时间: 2019-04-07 20:03

一、拦截器和过滤器介绍

  1. 基本介绍
    二者都是基于AOP编程思想的,先理解一下AOP的概念,AOP不是一种具体的技术,而是一种编程思想。在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。 但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以AOP——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现。
  2. 二者区别
    (1)Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
    (2)Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
    (3)Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
    (4)拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
    (5)拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
    (6)拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
    (7)在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
    (8)拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

二、过滤器+拦截器的执行顺序

  1. 过滤器是JavaEE标准,采用函数回调的方式进行。是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理。
    @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("before...");
            chain.doFilter(request, response);
            System.out.println("after...");
        }

    chain.doFilter(request, response);这个方法的调用作为分水岭。事实上调用Servlet的doService()方法是在chain.doFilter(request, response);这个方法中进行的。

  2. 拦截器是被包裹在过滤器之中的
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion");
        }

    a.preHandle()这个方法是在过滤器的chain.doFilter(request, response)方法的前一步执行,也就是在 [System.out.println("before...")][chain.doFilter(request, response)]之间执行。

    b.postHandle()方法在执行完controller逻辑后,在return ModelAndView之前进行,可以操控Controller的ModelAndView内容。

    c.afterCompletion()方法是在过滤器返回给前端前一步执行,也就是在[chain.doFilter(request, response)][System.out.println("after...")]之间执行。

  3. SpringMVC的机制是由同一个Servlet来分发请求给不同的Controller,其实这一步是在Servlet的service()方法中执行的。所以过滤器、拦截器、service()方法,dispatc()方法的执行顺序应该是这样的,大致画了个图:其实非常好测试,自己写一个过滤器,一个拦截器,然后在这些方法中都加个断点,一路F8下去就得出了结论。

转自和参考链接:

Spring Boot实战:拦截器与过滤器: https://www.cnblogs.com/paddix/p/8365558.html

Java过滤器与SpringMVC拦截器之间的关系与区别:https://www.cnblogs.com/csniper/p/5570386.html

0