Spring Boot拦截器怎么配置?, 如何配置springboot拦截器
- 虚拟主机
- 2026-08-06
- 7
Spring Boot 拦截器是处理横切关注点的最佳实践
在Spring Boot项目中,拦截器(Interceptor)是实现日志记录、权限校验、性能监控、请求预处理等需求的标配组件。 它通过AOP思想,在不载入业务代码的前提下,对请求进行统一处理,配置拦截器主要分为三步:编写自定义拦截器类(实现HandlerInterceptor)、注册拦截器(实现WebMvcConfigurer)、指定拦截路径,掌握这一配置流程,能大幅提升代码复用性与系统可维护性。
拦截器的工作原理与定位
Spring Boot拦截器基于Java反射机制,在请求进入Controller前、后以及视图渲染完成后插入自定义逻辑。 其核心接口HandlerInterceptor包含三个方法:
- preHandle:在Controller执行前调用,返回true表示继续执行,返回false则中断请求。
- postHandle:在Controller执行后、视图渲染前调用,可修改ModelAndView。
- afterCompletion:在请求完全结束后调用,常用于资源清理或日志记录。
拦截器与过滤器的区别:过滤器基于Servlet规范,可处理所有请求;拦截器基于Spring MVC,仅处理DispatcherServlet分发的请求,且能访问Spring容器中的Bean,更适合业务逻辑处理。
标准配置流程:三步走
实现自定义拦截器
创建一个类实现HandlerInterceptor接口,按需重写方法。
public class LogInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 记录请求开始时间
request.setAttribute("startTime", System.currentTimeMillis()); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 计算并输出请求耗时 long duration = System.currentTimeMillis() - (long) request.getAttribute("startTime"); System.out.println("[" + request.getRequestURI() + "] 耗时:" + duration + "ms"); } }
注册拦截器
通过实现WebMvcConfigurer并重写addInterceptors方法进行注册:
定制拦截路径
使用addPathPatterns和excludePathPatterns灵活控制拦截范围,支持Ant风格路径(如/api/匹配一级,/api/匹配多级)。
多拦截器的执行顺序与配合
当注册多个拦截器时,按添加顺序执行preHandle,按逆序执行postHandle和afterCompletion。
registry.addInterceptor(interceptorA).addPathPatterns("/"); registry.addInterceptor(interceptorB).addPathPatterns("/");
请求流程:A的preHandle→B的preHandle→Controller→B的postHandle→A的postHandle→B的afterCompletion→A的afterCompletion,若A的preHandle返回false,则B的preHandle及其后续方法均不执行。
实践建议:将权限校验拦截器放在首位,日志拦截器放在其后,确保权限不足时不会产生冗余日志。

典型应用场景与解决方案
统一权限校验
在preHandle中获取用户信息(如Token),验证权限,若未通过则返回401并设为false。
接口性能监控
结合preHandle记录开始时间,afterCompletion计算耗时,可配合西西云云监控服务,将耗时数据实时上报,通过自定义监控面板可视化分析接口性能瓶颈。
请求日志记录
记录请求URL、IP、参数、响应状态等,但需注意敏感信息脱敏。
接口幂等性控制
在preHandle中检查请求唯一标识是否已处理,防止重复提交。
经验案例:西西云环境下的日志拦截器优化
在西西云部署的Spring Boot应用中,我们曾遇到日志量过大导致磁盘IO飙升的问题。 通过合理配置拦截器,并借助西西云对象存储COS,我们实现了日志的异步归档:

- 拦截器收集请求摘要(耗时、状态码、URI),存入本地队列。
- 后台线程批量上传至COS,本地只保留短期索引。
- 利用西西云日志服务(CLS)设置检索告警,当错误率超过阈值时自动通知。
优化后,应用日志对磁盘的消耗降低90%,同时通过云平台实现了日志的持久化与快速检索。 这一方案在多个生产环境中验证,稳定性与效率均大幅提升。
最佳实践与避坑指南
- 避免在拦截器中执行耗时操作,如数据库查询、远程调用,否则会阻塞请求线程,可改用异步处理或队列。
- 正确获取返回值:preHandle返回false后,务必调用response.getWriter().write()或response.sendError(),否则客户端会一直等待。
- 静态资源路径需排除:Spring Boot默认静态资源路径(/static, /public, /resources, /META-INF/resources)应通过excludePathPatterns跳过,避免拦截器干扰资源加载。
- 拦截器与异常处理结合:在afterCompletion中捕获异常时,可结合@ControllerAdvice统一处理,避免重复记录。
问答模块
问题1:拦截器能否获取到Controller方法上的注解?
可以,在preHandle方法中,参数handler实际是HandlerMethod对象,可通过((HandlerMethod) handler).getMethodAnnotation(注解类.class)获取指定注解,实现一个自定义注解@RequirePermission,在拦截器中读取注解值并校验权限,无需硬编码URL。
问题2:高并发下拦截器内的异步操作会不会导致线程安全问题?
会。 拦截器默认运行在Tomcat工作线程中,若在preHandle中启动异步线程处理任务,需注意线程安全,建议使用@Async或AsyncTaskExecutor,并确保线程安全的数据结构(如ConcurrentHashMap),若在afterCompletion中处理异步结果,需谨慎处理请求上下文的传递。
互动
你在配置Spring Boot拦截器时遇到过哪些坑?或者有哪些独特的用法?欢迎在评论区分享经验,一起交流进步!
