详解java中,过滤器filter和拦截器interceptor的区别

在Java中,拦截器(Interceptor)和过滤器(Filter)是两个常用的概念,用于在应用程序中处理请求和响应。虽然它们的目标类似,但它们有一些区别:

  1. 触发时机:

    • 过滤器:过滤器在请求到达Servlet之前和离开Servlet之后执行,即在请求进入Web容器和响应离开Web容器之间执行。
    • 拦截器:拦截器在请求进入Controller之前和离开Controller之后执行,即在请求到达控制器和响应离开控制器之间执行。
  2. 应用范围:

    • 过滤器:过滤器是在Web容器级别上操作请求和响应的,可以对所有请求进行统一的处理。它们可以配置在web.xml文件中,并指定拦截的URL模式。
    • 拦截器:拦截器是在应用程序级别上操作请求和响应的,只作用于指定的处理器(如Controller)或特定的方法。它们是基于框架(如Spring MVC)提供的,以增强或修改特定请求的处理。
  3. 功能和用途:

    • 过滤器:过滤器主要用于请求预处理和响应后处理,例如身份验证、日志记录、编码转换或防止跨站点脚本攻击等。它们可以修改请求或响应的内容。
    • 拦截器:拦截器用于控制和管理请求的处理流程,例如权限验证、日志记录、性能监控或事务管理等。它们对请求的处理过程有更细粒度的控制。

拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

        具体来说:

        在拦截器中,可以通过依赖注入的方式获取IOC容器中的各个Bean,并且可以调用这些Bean来执行业务逻辑。这是因为拦截器是在Spring的上下文环境中运行的,能够访问和使用IOC容器中的对象。拦截器可以获取ioc中的service bean实现业务逻辑,拦截器可以获取ioc中的service bean实现业务逻辑,拦截器可以获取ioc中的service bean实现业务逻辑。

        而过滤器是在Servlet容器级别上运行的,它们不直接与Spring框架集成,因此无法直接访问或注入Spring的Bean。过滤器通常用于请求预处理和响应后处理,主要关注请求和响应的内容和参数,而不涉及具体的Spring Bean。

        所以,在需要访问和使用Spring IOC容器中的Bean时,应该选择使用拦截器,因为拦截器可以轻松地与Spring框架集成,并获取到所需的Bean进行业务处理。

触发时机:

1.过滤器和拦截器触发时机不一样:

  过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

2.过滤器的触发时机是容器后,servlet之前,所以过滤器的doFilter(

ServletRequest request, ServletResponse response, FilterChain chain

)的入参是ServletRequest ,而不是httpservletrequest。因为过滤器是在httpservlet之前。

详解java中,过滤器filter和拦截器interceptor的区别_第1张图片

过滤器是JavaEE标准,采用函数回调的方式进行。是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理。

 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);这个方法中进行的。

.拦截器是被包裹在过滤器之中的。

@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.preHandle()方法之后,在return ModelAndView之前进行,可以操控Controller的ModelAndView内容。

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

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

执行过程大概如下如所示:

详解java中,过滤器filter和拦截器interceptor的区别_第2张图片

总结:拦截器功在对请求权限鉴定方面确实很有用处,在我所参与的这个项目之中,第三方的远程调用每个请求都需要参与鉴定,所以这样做非常方便,而且他是很独立的逻辑,这样做让业务逻辑代码很干净。和框架的其他功能一样,原理很简单,使用起来也很简单,大致看了下SpringMVC这一部分的源码,其实还是比较容易理解的。

  我们项目中仅仅用到了preHandle这个方法,而未用其他的,框架提供了一个已经实现了拦截器接口的适配器类HandlerInterceptorAdapter,继承这个类然后重写一下需要用到的方法就行了,可以少几行代码,这种方式Java中很多地方都有体现。

你可能感兴趣的:(java,jar,spring,spring,boot,spring,cloud,jvm,servlet)