在 Spring Boot 中你是怎么使用拦截器的?
- 标签:Spring Boot、后端
🏛 业务架构师
我在 Spring Boot 中使用拦截器的标准三步:
1. 实现拦截器:
java
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req,
HttpServletResponse resp, Object handler) {
UserContext.set(tokenParser.parse(req.getHeader("Authorization")));
return true;
}
@Override
public void afterCompletion(...) { UserContext.clear(); } // 必清,防串号
}2. 注册 + 路径管理:
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**", "/actuator/**");
}
}3. 治理:拦截器保持薄(鉴权判断、上下文注入、审计打点),重逻辑下沉到专门服务。
架构师视角,拦截器在我的体系里承担接入层标准化:
- 网关完成认证后,拦截器负责"身份落地"——把 userId/tenantId 放进 ThreadLocal,业务代码无感取用;
- 接口耗时与访问日志统一打点,业务零侵入;
- 灰度标记、locale、租户路由都在这里注入。
两个必抓的纪律:afterCompletion 必须清理 ThreadLocal(线程池复用会串用户,资金级事故);拦截器顺序与路径规则集中在一个配置类管理,禁止各业务组私自注册——顺序混乱的鉴权拦截器是真实的安全事故来源。公司级拦截器我会进一步封装进 starter,业务方想错都难。
🏗 系统架构师
三步接入:
java
@Component
public class AuthInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) {
// 校验 token,写入用户/租户上下文
return true;
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**")
.order(1);
}
}我的使用纪律:
- 职责限定 Web 层横切:登录态、租户、traceId、审计;不放业务逻辑;
- preHandle 必须轻:token 校验走本地缓存(JWKS 缓存),别每请求打一次远程认证;重操作下沉网关;
- afterCompletion 清理上下文(ThreadLocal/MDC),线程池复用串号是经典事故;
- order 显式声明:认证 → 鉴权 → 审计的顺序不能靠注册顺序的巧合;
- 异步请求(DeferredResult/WebAsync)注意 AsyncHandlerInterceptor 的并发分发语义。
💻 全栈开发专家
四步走(登录态注入为例):
java
// 1. 实现拦截器
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) {
if (!(handler instanceof HandlerMethod)) return true; // 静态资源放行
UserContext.set(jwtVerifier.verify(req.getHeader("Authorization")));
return true;
}
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse resp,
Object handler, Exception ex) {
UserContext.remove(); // 铁律:线程复用,不清就串号/泄漏
}
}
// 2+3. 注册并配规则
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login", "/actuator/**", "/doc.html")
.order(10);
}
}
// 4. 业务里 UserContext.get() 取登录用户工程细节我额外守三条:exclude 必须包含 actuator 和文档路径,不然监控、swagger 被拦(发布事故常客);拦截器里只做轻校验,重查询(权限点)下沉或缓存;操作日志放 afterCompletion(异常场景也要记)。排障顺序:路径 pattern 写错没匹配上 > order 顺序不对 > 异常被全局处理器先接走。