Spring Boot中HTTP请求拦截与请求头设置实践

发布时间:2026/7/30 10:27:04
Spring Boot中HTTP请求拦截与请求头设置实践 1. 为什么需要拦截HTTP请求并设置请求头在Spring Boot应用开发中拦截HTTP请求并修改请求头是一种常见需求。我最近在一个企业级项目中就遇到了这样的场景需要为所有对外请求统一添加认证令牌Token同时还要处理一些跨域相关的头信息。这种需求在微服务架构中尤为常见。HTTP请求拦截器Interceptor的工作原理类似于安检通道。当请求进入应用时它会先经过我们设置的安检关卡在这里我们可以检查、修改甚至拒绝请求。与过滤器(Filter)不同拦截器工作在更上层能够获取到Spring的上下文信息使用起来更加灵活。2. 实现HTTP请求拦截的基础配置2.1 创建自定义拦截器类首先我们需要创建一个实现HandlerInterceptor接口的类。这个接口定义了三个关键方法public class CustomHeaderInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 在控制器方法执行前调用 return true; // 返回false将中断请求 } Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { // 控制器方法执行后视图渲染前调用 } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 整个请求完成后调用 } }2.2 注册拦截器到Spring容器创建配置类来注册我们的拦截器Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new CustomHeaderInterceptor()) .addPathPatterns(/api/**) // 拦截路径 .excludePathPatterns(/api/public/**); // 排除路径 } }这里有几个关键点需要注意addPathPatterns指定需要拦截的URL模式excludePathPatterns可以设置白名单顺序很重要 - 多个拦截器会按注册顺序执行3. 请求头的实际操作技巧3.1 添加自定义请求头在preHandle方法中我们可以这样添加头信息Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { response.setHeader(X-Custom-Header, my-value); response.setHeader(Cache-Control, no-cache); return true; }3.2 修改现有请求头有时我们需要修改而不是添加头信息。需要注意的是HTTP协议中有些头是不能被修改的Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String authHeader request.getHeader(Authorization); if (authHeader ! null authHeader.startsWith(Basic)) { response.setHeader(Authorization, Bearer authHeader.substring(5)); } return true; }3.3 处理CORS头信息跨域资源共享(CORS)是现代Web应用常见需求Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { response.setHeader(Access-Control-Allow-Origin, *); response.setHeader(Access-Control-Allow-Methods, GET, POST, PUT, DELETE); response.setHeader(Access-Control-Allow-Headers, Content-Type, Authorization); response.setHeader(Access-Control-Max-Age, 3600); return true; }4. 高级应用场景与最佳实践4.1 微服务间的认证传递在微服务架构中经常需要在服务间传递认证信息Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String authToken request.getHeader(X-Auth-Token); if (authToken null) { authToken generateNewToken(); } MDC.put(authToken, authToken); // 放入日志上下文 response.setHeader(X-Auth-Token, authToken); return true; }4.2 请求追踪与日志关联为请求添加唯一ID便于日志追踪Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String requestId UUID.randomUUID().toString(); response.setHeader(X-Request-ID, requestId); MDC.put(requestId, requestId); return true; }4.3 性能监控与统计可以添加一些性能相关的头信息private static final ThreadLocalLong startTime new ThreadLocal(); Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { startTime.set(System.currentTimeMillis()); return true; } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { Long start startTime.get(); if (start ! null) { long duration System.currentTimeMillis() - start; response.setHeader(X-Processing-Time, duration ms); startTime.remove(); } }5. 常见问题与解决方案5.1 拦截器不生效的可能原因路径匹配问题检查addPathPatterns是否配置正确顺序问题多个拦截器可能有执行顺序问题Spring Boot版本差异不同版本可能有细微差别被其他组件拦截如Security过滤器可能先于拦截器执行5.2 头信息被覆盖或丢失某些服务器或代理可能会修改或删除头信息。解决方案使用标准头名称考虑使用前缀如X-表示自定义头检查服务器配置如Tomcat的server.xml5.3 性能考量拦截器会增加请求处理时间特别是在添加复杂逻辑时。建议避免在拦截器中执行耗时操作考虑异步处理非关键逻辑对性能敏感路径设置白名单6. 与其他技术的对比与整合6.1 拦截器 vs 过滤器特性拦截器(Interceptor)过滤器(Filter)工作层级Spring MVC层面Servlet容器层面依赖依赖Spring框架不依赖Spring获取信息可以获取Handler信息只能获取Servlet信息执行顺序在过滤之后在拦截器之前6.2 与Spring Security整合当同时使用Spring Security时需要注意执行顺序Configuration Order(Ordered.HIGHEST_PRECEDENCE 1) // 设置执行顺序 public class WebConfig implements WebMvcConfigurer { // 配置代码 }6.3 在WebFlux中的应用对于响应式应用需要使用WebFilter而不是HandlerInterceptorComponent public class CustomWebFilter implements WebFilter { Override public MonoVoid filter(ServerWebExchange exchange, WebFilterChain chain) { exchange.getResponse().getHeaders() .add(X-Custom-Header, reactive-value); return chain.filter(exchange); } }在实际项目中我通常会创建一个基础的拦截器框架然后根据不同的业务需求进行扩展。例如我们可能需要在开发、测试和生产环境设置不同的头信息这时可以通过Spring的Profile功能来实现环境特定的配置。一个实用的技巧是使用拦截器来统一处理API版本控制。通过在请求头中添加版本信息后端可以据此提供不同版本的服务Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String apiVersion request.getHeader(X-API-Version); if (apiVersion null) { apiVersion v1; // 默认版本 } request.setAttribute(apiVersion, apiVersion); return true; }最后要提醒的是虽然拦截器功能强大但也不应滥用。每个添加到拦截器中的逻辑都会影响所有匹配的请求因此要保持拦截器的职责单一避免变成上帝类。