Spring Web开发中拦截器(Interceptor)和过滤器(Filter)的区别

拦截器(Interceptor)和过滤器(Filter)是Web开发中常用的两种机制,用于在请求到达最终处理逻辑之前或响应返回客户端之前执行特定的操作。它们虽然有一些相似之处,但在实现、用途和执行顺序上存在显著区别。以下是它们的详细比较:

基本概念

过滤器(Filter)

  • 过滤器是Servlet规范的一部分,定义在javax.servlet包中。实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用
  • 过滤器主要用于对请求和响应进行预处理和后处理,可以拦截所有进入Servlet容器的请求。

拦截器(Interceptor)

  • 拦截器则和Servlet无关,由Spring框架实现。拦截器是Spring MVC框架的一部分,定义在org.springframework.web.servlet包中。
  • 拦截器主要用于拦截Spring MVC的控制器请求,通常用于处理与业务逻辑相关的横切关注点。
  • 一般基于 Java 的反射机制实现,属于AOP的一种运用。
    常用的Spring中的拦截器有:HandlerInterceptor、MethodInterceptor

执行顺序

过滤器

  • 过滤器在Servlet容器级别工作,执行顺序由web.xml中的配置顺序或注解的@Order注解决定。
  • 过滤器链的执行顺序是固定的,按照配置的顺序依次执行。

拦截器

  • 拦截器在Spring MVC的DispatcherServlet级别工作,执行顺序由Spring MVC的配置类中的注册顺序决定。
  • 拦截器链的执行顺序也是固定的,按照注册的顺序依次执行。

 作用范围

过滤器

  • 过滤器作用于所有进入Servlet容器的请求,包括静态资源(如CSS、JavaScript文件)和动态请求(如Servlet、JSP)。
  • 过滤器通常用于全局性的请求处理,如字符编码设置、日志记录、压缩响应等。

拦截器

  • 拦截器仅作用于Spring MVC的控制器请求,不会拦截静态资源或其他非Spring MVC处理的请求。
  • 拦截器通常用于业务逻辑相关的处理,如权限验证、会话管理、性能监控等。

 实现方式

过滤器

  • 实现Filter接口,并重写doFilter方法。
  • 通过web.xml配置或使用@WebFilter注解进行注册。
  • @Component注解。
package com.conch.hrx.cb.Filter;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import java.io.IOException;

@Component
public class LoggingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。「注意」:这个方法必须执行成功,否则过滤器会不起作用。");
        // 用于完成 Filter 的初始化
        Filter.super.init(filterConfig);
        System.out.println("Filter 完成初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。");
        chain.doFilter(request, response);
        System.out.println("Filter doFilter()过滤逻辑执行结束");
    }

    @Override
    public void destroy() {
        System.out.println("destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。");
        // 用于 Filter 销毁前,完成某些资源的回收;
        Filter.super.destroy();
        System.out.println("Filter 完成销毁");
    }
}

拦截器

  • 实现HandlerInterceptor接口,并重写preHandlepostHandleafterCompletion方法。
  • 通过Spring MVC的配置类(如WebMvcConfigurer)中的addInterceptors方法进行注册。
  • MethodInterceptor实现方式参照我的另一篇AOP介绍的博文:JVM动态代理和JDK动态代理介绍-优快云博客
package com.conch.hrx.cb.AITest.Interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoggingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor 前置逻辑处理:这个方法将在进入Controller之前进行预处理。「注意」:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor 处理中:只有在 preHandle() 方法返回值为true 时才会执行。会在Controller 中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("Interceptor 后置:只有在 preHandle() 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。");
    }
}
package com.conch.hrx.cb.config;

import com.conch.hrx.cb.AITest.Interceptor.LoggingInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        //  /**表示拦截所有的路径
        registry.addInterceptor(new LoggingInterceptor()).addPathPatterns("/**");
    }
}

运行结果:

容器初始化时会调用init()方法

 具体调用接口时会调用Filter和Interceptor逻辑

典型应用场景

过滤器

  • 设置请求和响应的字符编码。
  • 记录所有请求的日志。
  • 对响应内容进行压缩(如GZIP)。
  • 实现安全过滤(如XSS防护)。

拦截器

  • 进行用户认证和授权。注意:Spring Security 底层主要通过一组过滤器链(Filter Chain)来实现认证和授权功能。这些过滤器在请求到达实际的业务逻辑处理代码之前,对请求进行拦截和处理。
  • 记录控制器处理请求的时间。
  • 在请求处理前后进行特定的业务逻辑处理。

总结

  • 过滤器更适合于全局性的、与Servlet容器紧密相关的请求处理,如字符编码、日志记录、压缩等。
  • 拦截器更适合于与业务逻辑相关的请求处理,如权限验证、会话管理、性能监控等。
  • 执行顺序上,过滤器在请求进入Servlet容器时首先执行,而拦截器在请求到达Spring MVC控制器之前执行。

选择使用过滤器还是拦截器,取决于你的具体需求和应用场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chen2017sheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值