Skip to content

在 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);
    }
}

我的使用纪律:

  1. 职责限定 Web 层横切:登录态、租户、traceId、审计;不放业务逻辑;
  2. preHandle 必须轻:token 校验走本地缓存(JWKS 缓存),别每请求打一次远程认证;重操作下沉网关;
  3. afterCompletion 清理上下文(ThreadLocal/MDC),线程池复用串号是经典事故;
  4. order 显式声明:认证 → 鉴权 → 审计的顺序不能靠注册顺序的巧合;
  5. 异步请求(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 顺序不对 > 异常被全局处理器先接走。