Spring MVC 拦截器与过滤器的区别及执行顺序

一、拦截器(Interceptor) vs 过滤器(Filter)

特性 拦截器(Interceptor) 过滤器(Filter)
作用范围 Spring MVC 框架层面 Servlet 容器层面
依赖框架 需 Spring 容器支持 原生 Servlet 规范
访问对象 可访问 HandlerMethod、ModelAndView 等对象 仅能访问 ServletRequest/Response
业务关联 可获取 Spring Bean 和业务数据 无法直接访问 Spring 上下文
触发时机 在 Controller 方法前后执行 在请求进入 Servlet 前/响应返回后执行
异常处理 可通过 @ControllerAdvice 统一处理 需在 web.xml 配置错误页面

二、执行顺序

flowchart TD A[请求] --> B(Filter#doFilter) B --> C(Interceptor#preHandle) C --> D[Controller] D --> E(Interceptor#postHandle) E --> F(Interceptor#afterCompletion) F --> G(Filter#doFilter后续逻辑) G --> H[响应]
  1. 过滤器链(FilterChain)web.xml声明顺序依次执行或者按过滤器名称
  2. 拦截器链(Interceptor) 按注册顺序执行 preHandle(先进先出) 逆序执行 postHandleafterCompletion(后进先出)

三、案例:定义多个拦截器(完整配置示例)

java 复制代码
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 InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 1. 日志拦截器(最先执行)
        registry.addInterceptor(new LogInterceptor())
                .addPathPatterns("/**")
                .order(1); // 数字越小优先级越高

        // 2. 认证拦截器
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/secure/**")
                .excludePathPatterns("/secure/public")
                .order(2);

        // 3. 性能监控拦截器(最后执行)
        registry.addInterceptor(new PerformanceInterceptor())
                .addPathPatterns("/api/**")
                .order(3);
    }
}

// 示例拦截器实现
class LogInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("[Log] Request URI: " + request.getRequestURI());
        return true;
    }
}

class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (request.getSession().getAttribute("user") == null) {
            response.setStatus(401);
            return false;
        }
        return true;
    }
}

class PerformanceInterceptor implements HandlerInterceptor {
    private ThreadLocal<Long> startTime = new ThreadLocal<>();
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        startTime.set(System.currentTimeMillis());
        return true;
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.printf("[Performance] %s took %d ms%n", 
            request.getRequestURI(), 
            System.currentTimeMillis() - startTime.get()
        );
    }
}
3.1 关键配置说明
  1. 执行顺序控制 order()方法指定优先级(值越小越先执行)
  2. 路径匹配规则 addPathPatterns():设置需拦截的路径(支持 Ant 风格) excludePathPatterns():设置排除路径
  3. 拦截器生命周期 preHandle:Controller 方法执行前 postHandle:Controller 执行后,视图渲染前 afterCompletion:请求完成后(总会执行)

💡 最佳实践:将公共拦截器(如日志、跨域)设为高优先级,业务拦截器(如权限)设为低优先级。

相关推荐
zzzll11112 小时前
Spring Boot 实现数据脱敏:自定义注解 + Jackson 序列化器
java·spring boot·后端
vx-Biye_Design6 小时前
SSM伴侣动物伴护星小程序06330-计算机课程设计、毕业设计
spring boot·后端·elasticsearch·小程序·架构·课程设计·idea
2分钟速写快排8 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
面向Google编程8 小时前
Apache Iceberg Variant 类型:v3 半结构化数据不再「二选一」
大数据·后端
jason成都9 小时前
Spring WebFlux 适配达梦新方案|dm‑r2dbc:Netty 异步传输的实验性 R2DBC 驱动
java·后端·spring
北岛贰10 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
IT_陈寒13 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端
小兵金林13 小时前
AI 生成代码的思考与实践
后端·ai编程
码事漫谈13 小时前
DeepSeek 明天又降价(涵历史价格对比)
后端
前端精髓13 小时前
NestJS 是什么(对着 Spring Boot 一起学习)
spring boot·后端·学习