SpringMVC拦截器怎么配置?拦截器配置详细步骤,常见问题解答

Spring MVC 拦截器(Interceptor)是 Spring Web MVC 框架提供的一种面向切面编程的轻量级机制,用于在处理器方法(Controller)调用前、调用后以及视图渲染完成后执行自定义逻辑,它的配置方式清晰、执行顺序可控、与业务解耦,是构建权限校验、日志记录、性能监控、请求审计等横切关注点的首选方案,相比 Filter(过滤器),拦截器深度集成 Spring 容器,可以注入任何 Spring Bean,因此在实际企业级项目中应用更广泛、更灵活。


拦截器的三种配置方式(基于 Spring MVC)

XML 方式最传统,适合老项目

spring-mvc.xmldispatcher-servlet.xml 中使用 <mvc:interceptors>

<mvc:interceptors>
    <!-- 全局拦截器:拦截所有请求 -->
    <bean class="com.example.interceptor.AuthInterceptor"/>
    <!-- 路径拦截器:只拦截特定路径 -->
    <mvc:interceptor>
        <mvc:mapping path="/api/"/>
        <mvc:exclude-mapping path="/api/login"/>
        <bean class="com.example.interceptor.ApiInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

Java Config 方式推荐,类型安全

实现 WebMvcConfigurer 接口并重写 addInterceptors 方法:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/")
                .excludePathPatterns("/login", "/register", "/static/");
    }
}

注解驱动 + 自定义注解精准控制,适合细粒度鉴权

通过自定义注解配合拦截器,实现方法级别的权限控制:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermission {
    String value();
}

在拦截器中通过 HandlerMethod 获取注解并校验,这种方式能够将权限逻辑从业务代码中完全剥离,维护性极佳


拦截器核心方法详解(推荐直接复用的基类)

Spring MVC 提供了 HandlerInterceptor 接口,包含三个默认方法(Java 8+ 默认方法),建议继承 HandlerInterceptorAdapter(旧版)或直接实现接口:

  • preHandle:在 Controller 方法执行前调用。返回 true 继续执行,返回 false 则中断请求,适合做登录校验、黑名单拦截、参数预处理。
  • postHandle:Controller 执行后、视图渲染前调用,适合修改 ModelAndView、统一添加公共数据。
  • SpringMVC拦截器怎么配置?拦截器配置详细步骤,常见问题解答

  • afterCompletion:请求完成后回调(无论是否异常),适合清理资源、记录日志、统计耗时

重要:若 preHandle 返回 false,则后续的 postHandleafterCompletion 都不会执行,且同链路上已执行过 preHandle 的拦截器的 afterCompletion 会逆序执行。


执行顺序与常见误区(干货)

拦截器的执行顺序遵循责任链模式,但存在一个关键细节:

  • 若配置了多个拦截器 A、B,则执行顺序为:A.preHandle → B.preHandle → Controller → B.postHandle → A.postHandle → 视图渲染 → B.afterCompletion → A.afterCompletion
  • preHandle 顺序执行postHandleafterCompletion 逆序执行

常见误区:

  • 误区一:认为 postHandle 一定能执行,实际上如果 Controller 抛出异常,postHandle 不会执行,只有 afterCompletion 会执行。
  • 误区二:拦截器只拦截 Controller 方法,不拦截静态资源,若需拦截静态资源,需要配置 <mvc:resources> 与拦截器路径同时覆盖,或者直接使用 Filter。
  • 误区三:拦截器与过滤器混淆,Filter 属于 Servlet 规范,基于容器,拦截所有请求包括静态资源;拦截器属于 Spring MVC,只针对 DispatcherServlet 路由的处理器。权限校验优先用拦截器,字符编码、CORS 等基础过滤优先用 Filter

实战:完整登录拦截器 + 性能监控(附代码)

以下代码展示一个可复用的登录校验与性能统计拦截器,同时解决异步请求时 afterCompletion 中获取用户信息可能失效的问题(通过 HandlerMethodThreadLocal 隔离):

public class AuthAndMonitorInterceptor implements HandlerInterceptor {
    private static final ThreadLocal<Long> START_TIME = new ThreadLocal<>();
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
            throws Exception {
        // 性能监控开始
        START_TIME.set(System.currentTimeMillis());
        // 身份校验逻辑
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            // 检查类/方法上的 @RequiresPermission 注解
            RequiresPermission perm = hm.getMethodAnnotation(RequiresPermission.class);
            if (perm != null && !checkPermission(request, perm.value())) {
                response.setStatus(403);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{"code":403,"msg&qu

SpringMVC拦截器怎么配置?拦截器配置详细步骤,常见问题解答

ot;:"无权限"}"); return false; // 中断请求,不再执行后续逻辑 } } // 如为登录接口或公开接口,放行 return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { Long start = START_TIME.get(); if (start != null) { long cost = System.currentTimeMillis() - start; System.out.println(request.getRequestURI() + " 耗时: " + cost + "ms"); START_TIME.remove(); // 防止线程池复用导致数据错乱 } } private boolean checkPermission(HttpServletRequest request, String perm) { // 从 Session 或 Token 中解析权限,这里做简化演示 return request.getSession().getAttribute("user") != null; } }

配置该拦截器(Java Config):

registry.addInterceptor(new AuthAndMonitorInterceptor())
        .addPathPatterns("/")
        .excludePathPatterns("/login", "/error", "/static/");

酷番云经验案例:高并发场景下的拦截器线程安全实践

酷番云在服务某金融级客户时遇到一个典型问题:拦截器中使用了非线程安全的成员变量来存储请求上下文,导致高并发下用户数据串号,我们当时给出的方案是结合酷番云云服务器(SSD 高性能实例)进行压测验证,最终落地了以下实践:

  1. 禁止在拦截器中定义可变的成员变量,必须使用 ThreadLocal 或在方法栈内传递数据。
  2. 对于需要全局共享的只读配置(比如白名单路径列表),使用 volatile 修饰并只读初始化,避免并发失效。
  3. 利用酷番云的弹性伸缩能力,在流量高峰前预置多台云服务器,同时利用缓存的 excludePathPatterns 配置热更新通过酷番云对象存储下发配置,拦截器内定期拉取,实现免重启更新拦截规则。
  4. 经过压测,性能瓶颈不在拦截器,而在于数据库连接和日志同步写,于是我们将日志改为异步写入酷番云日志服务,拦截器只负责采集,显著提升吞吐量。

核心观点:拦截器配置本身简单,但企业级应用必须关注并发安全、性能监控和可观测性,建议在拦截器内只做轻量级逻辑,杜绝数据库查询、远程调用等耗时操作,如有需要可结合消息队列异步化。


性能对比与最佳实践(E-E-A-T 经验总结)

方式 性能影响 使用场景 推荐度
XML 配置 无额外开销,启动加载略慢 老项目维护
Java Config

SpringMVC拦截器怎么配置?拦截器配置详细步骤,常见问题解答

无额外开销,类型安全

新项目、Spring Boot 项目
自定义注解拦截反射少量开销细粒度权限控制
多个拦截器链每个请求多几次方法调用拆分为独立职责

最佳实践清单:

  • 登录校验日志监控拆分为两个独立拦截器,遵循单一职责。
  • 所有拦截器路径用 覆盖大部分场景,再用 excludePathPatterns 排除登录、静态资源、异常页。
  • 在拦截器中不要捕获所有异常,让异常交给 @ControllerAdvice 统一处理。
  • 如需在 postHandle 中访问用户信息,务必确保信息存储与当前线程绑定,避免异步线程穿透。

相关问答模块

问题1:Spring MVC 拦截器和 Filter 过滤器有什么区别?什么时候选拦截器?

:两者本质不同。Filter 是 Servlet 规范的一部分,由容器管理,注册在 web.xml 或 @WebFilter 中,可以拦截一切请求(包括静态资源、JSP);而拦截器是 Spring MVC 的组件,只拦截进入 DispatcherServlet 的请求,并且可以方便地注入 Spring Bean,对于纯 HTTP 层面的处理(如字符编码、CORS、防 XSS 攻击),优先选择 Filter;对于需要与 Spring 业务上下文交互的逻辑(如权限校验、用户会话检查、controller 层日志监听),拦截器更合适,另外拦截器还可以通过 HandlerMethod 获取方法上的注解,实现非常灵活的细粒度控制,这是 Filter 做不到的。

问题2:如何在拦截器中访问 Spring 配置文件中的属性(如白名单路径)?

:有几种推荐方式,第一,通过构造器注入:在 Java Config 中将 @Value 配置传给拦截器实例;第二,在拦截器中通过 WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext()) 获取容器并 getBean,但不推荐,耦合高;第三,使用 @Component 注册拦截器,并在拦截器内部使用 @Value 注入属性。最优做法是在 WebMvcConfigaddInterceptors 方法中直接构造拦截器并传入 @Value 参数,这样避免拦截器作为 Bean 被其他组件误依赖,同时保持清晰的配置入口。

public void addInterceptors(InterceptorRegistry registry) {
    AuthInterceptor interceptor = new AuthInterceptor(whitelist);
    registry.addInterceptor(interceptor).addPathPatterns("/");
}

互动一下:你在实际项目中踩过拦截器执行顺序的坑吗?或者对拦截器与 AOP 的结合使用有独到心得?欢迎在评论区分享你的真实案例,一起讨论更好的实践方案!

图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/728790.html

(0)
上一篇 2026年8月27日 02:56
下一篇 2026年8月27日 02:57

相关推荐

  • 穿越火线最低配置要求是什么?玩CF需要什么电脑配置?

    穿越火线作为一款经典的第一人称射击网游,对硬件的要求并不苛刻,但要想在实战中保持稳定高帧率、避免卡顿掉帧,仅仅满足官方最低配置远远不够,核心结论是:最低配置仅能保证游戏启动,若要流畅竞技,需将CPU性能、内存容量和显卡配置提升至推荐水平,并做好系统与网络优化,以下从配置标准、性能瓶颈、优化方案和实战案例四个维度……

    2026年8月24日
    0215
  • xp配置环境变量怎么设置,电脑系统环境变量配置教程

    XP配置环境变量:系统性能优化与开发环境搭建的核心基石在Windows XP这一经典操作系统中,环境变量是连接系统内核、应用程序与用户操作的关键桥梁,正确配置环境变量并非简单的系统设置,而是决定软件能否正常运行、系统资源能否高效调用的核心手段,对于开发者而言,它是构建编译环境的基础;对于普通用户,它是解决“命令……

    2026年5月27日
    01443
    • 服务器间歇性无响应是什么原因?如何排查解决?

      根源分析、排查逻辑与解决方案服务器间歇性无响应是IT运维中常见的复杂问题,指服务器在特定场景下(如高并发时段、特定操作触发时)出现短暂无响应、延迟或服务中断,而非持续性的宕机,这类问题对业务连续性、用户体验和系统稳定性构成直接威胁,需结合多维度因素深入排查与解决,常见原因分析:从硬件到软件的多维溯源服务器间歇性……

      2026年1月10日
      020
  • 分布式数据库案例

    分布式数据库案例金融行业的实践:蚂蚁集团的OceanBase在金融领域,数据一致性、高可用性和海量存储需求是分布式数据库的核心挑战,蚂蚁集团的OceanBase是这一领域的典型代表,作为支撑支付宝等金融场景的核心数据库,OceanBase自2010年开始研发,旨在解决传统单机数据库在扩展性、容灾能力上的瓶颈,O……

    2025年12月26日
    02760
  • Win7配置显卡

    在Windows 7系统中配置显卡,核心结论是:必须严格遵循“驱动匹配、环境纯净、性能调优”三大原则,优先通过微软官方渠道或显卡厂商官网获取经过WHQL认证的驱动程序,并结合系统底层设置释放硬件性能, 尽管Win7已停止主流支持,但在特定工业控制、老旧游戏兼容及私有云渲染节点场景中,其稳定性依然不可替代,若配置……

    2026年6月22日
    0985

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注