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

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


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

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

在 spring-mvc.xml 或 dispatcher-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,则后续的 postHandle 和 afterCompletion 都不会执行,且同链路上已执行过 preHandle 的拦截器的 afterCompletion 会逆序执行。


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

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

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

常见误区:

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

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

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

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 注入属性。最优做法是在 WebMvcConfig 的 addInterceptors 方法中直接构造拦截器并传入 @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

相关推荐

  • 家庭用笔记本电脑配置怎么选,家庭用笔记本电脑什么配置好

    家庭用笔记本电脑配置选购核心结论家庭用笔记本电脑无需盲目追求顶级性能,按家庭成员实际使用场景匹配配置才是关键, 多数家庭共用一台电脑,涵盖办公、网课、影音娱乐与轻度创作,因此均衡型中端配置(标压或准标压处理器 + 16GB内存 + 512GB固态硬盘 + 2.5K高色域屏幕)是绝大多数家庭的最优解,这个配置区间……

    2026年8月11日
    01410
  • 配置交换机接口IP,配置交换机接口IP地址

    配置交换机接口IP的核心逻辑与实战指南配置交换机接口IP并非简单的地址分配,而是构建三层网络通信、实现VLAN间路由及远程管理的基石,核心结论在于:必须明确区分接入层与汇聚/核心层交换机的角色定位,严格遵循“单臂路由”或“三层交换”的最佳实践,并配合ACL与安全策略,才能确保网络的高可用性与安全性, 对于大多数……

    2026年6月2日
    02813
  • Centos dns服务配置怎么做?dns服务配置教程

    在 CentOS 系统中构建高可用、低延迟的 DNS 服务,核心在于精准选择轻量级解析软件(如 Bind 或 Dnsmasq)并实施严格的访问控制策略,对于绝大多数生产环境,优先推荐采用 Dnsmasq 作为本地缓存解析器,配合上游权威 DNS 实现快速响应;而对于需要复杂区域转发或权威托管的场景,则应部署 B……

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

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

      2026年1月10日
      020
  • 怎么提高配置,电脑配置不足怎么升级最有效?

    提高配置的本质是匹配业务需求,而非单纯堆砌硬件无论是网站响应缓慢、应用并发不足,还是服务器频繁告警,提高配置的核心逻辑永远是:先诊断瓶颈,再精准扩容,最后通过架构优化让硬件资源发挥最大效用,盲目升级CPU或内存,往往造成成本浪费而问题依旧,真正专业的配置提升方案,应当基于业务场景、访问特征和数据增长趋势,采用……

    2026年8月25日
    0893

发表回复

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

评论列表(5条)

  • lucky936fan的头像
    lucky936fan 2026年8月27日 05:49

    读了这篇文章,我深有感触。作者对返回的理解非常深刻,论述也很有逻辑性。内容既有理论深度,又有实践指导意义,确实是一篇值得细细品味的好文章。希望作者能继续创作更多优秀的作品!

    • kind422man的头像
      kind422man 2026年8月27日 05:51

      @lucky936fan:读了这篇文章,我深有感触。作者对返回的理解非常深刻,论述也很有逻辑性。内容既有理论深度,又有实践指导意义,确实是一篇值得细细品味的好文章。希望作者能继续创作更多优秀的作品!

  • brave440girl的头像
    brave440girl 2026年8月27日 05:49

    这篇文章的内容非常有价值,我从中学习到了很多新的知识和观点。作者的写作风格简洁明了,却又不失深度,让人读起来很舒服。特别是返回部分,给了我很多新的思路。感谢分享这么好的内容!

  • 萌兴奋1783的头像
    萌兴奋1783 2026年8月27日 05:49

    这篇文章写得非常好,内容丰富,观点清晰,让我受益匪浅。特别是关于返回的部分,分析得很到位,给了我很多新的启发和思考。感谢作者的精心创作和分享,期待看到更多这样高质量的内容!

  • 草梦4638的头像
    草梦4638 2026年8月27日 05:50

    这篇文章写得非常好,内容丰富,观点清晰,让我受益匪浅。特别是关于返回的部分,分析得很到位,给了我很多新的启发和思考。感谢作者的精心创作和分享,期待看到更多这样高质量的内容!