发布时间:2026/7/30 10:17:34
Spring Boot拦截HTTP请求与设置请求头实战指南 1. Spring Boot拦截HTTP请求设置请求头的核心场景在Web开发中经常需要统一处理HTTP请求和响应。比如在微服务架构中我们可能需要在所有请求中添加认证头如JWT Token或者记录请求日志、修改响应内容。Spring Boot提供了多种方式来实现这种拦截需求其中最常见的是通过过滤器Filter和拦截器Interceptor。关键区别Filter是Servlet规范的一部分工作在更底层Interceptor是Spring MVC的组件可以访问Spring上下文。我最近在一个电商项目中就遇到了这样的需求需要在所有API请求中添加一个X-Request-ID头用于全链路追踪。经过对比几种方案最终选择了过滤器的方式实现。下面分享具体实现过程和踩过的坑。2. 实现HTTP请求拦截的三种核心方式2.1 使用Servlet Filter这是最基础的方式适合简单的请求/响应修改。创建一个实现javax.servlet.Filter接口的类public class CustomHeaderFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) request; HttpServletResponse httpResponse (HttpServletResponse) response; // 添加自定义请求头 httpResponse.setHeader(X-Custom-Header, value); // 继续过滤器链 chain.doFilter(httpRequest, httpResponse); } }注册过滤器有两种方式使用Component注解自动注册通过FilterRegistrationBean手动注册推荐可以控制顺序Configuration public class FilterConfig { Bean public FilterRegistrationBeanCustomHeaderFilter filterRegistrationBean() { FilterRegistrationBeanCustomHeaderFilter registration new FilterRegistrationBean(); registration.setFilter(new CustomHeaderFilter()); registration.addUrlPatterns(/*); registration.setOrder(1); // 设置过滤器顺序 return registration; } }2.2 使用Spring InterceptorInterceptor可以访问Spring上下文更适合需要依赖注入的场景。实现步骤创建拦截器类实现HandlerInterceptorpublic class CustomHeaderInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { response.setHeader(X-Interceptor-Header, interceptor-value); return true; } }注册拦截器Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new CustomHeaderInterceptor()) .addPathPatterns(/**); } }2.3 使用ControllerAdvice ResponseBodyAdvice对于只需要修改响应体的场景可以使用这个组合ControllerAdvice public class CustomHeaderAdvice implements ResponseBodyAdviceObject { Override public boolean supports(MethodParameter returnType, Class? extends HttpMessageConverter? converterType) { return true; } Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class? extends HttpMessageConverter? selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { response.getHeaders().add(X-Advice-Header, advice-value); return body; } }3. 实战实现全链路请求ID追踪下面通过一个完整示例演示如何在微服务中实现请求追踪。我们需要如果请求没有X-Request-ID头生成一个UUID将该ID添加到响应头在日志中记录这个ID3.1 创建RequestIdFilterpublic class RequestIdFilter implements Filter { private static final String REQUEST_ID_HEADER X-Request-ID; private static final Logger logger LoggerFactory.getLogger(RequestIdFilter.class); Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) request; HttpServletResponse httpResponse (HttpServletResponse) response; // 获取或生成请求ID String requestId httpRequest.getHeader(REQUEST_ID_HEADER); if (requestId null || requestId.isEmpty()) { requestId UUID.randomUUID().toString(); } // 添加到响应头 httpResponse.setHeader(REQUEST_ID_HEADER, requestId); // 使用MDC记录请求ID便于日志追踪 MDC.put(requestId, requestId); try { logger.info(Incoming request: {} {}, httpRequest.getMethod(), httpRequest.getRequestURI()); chain.doFilter(httpRequest, httpResponse); } finally { MDC.remove(requestId); } } }3.2 配置日志模式在application.properties中添加logging.pattern.console%d{yyyy-MM-dd HH:mm:ss} [%thread] [%X{requestId}] %-5level %logger{36} - %msg%n3.3 注册过滤器Configuration public class WebConfig { Bean public FilterRegistrationBeanRequestIdFilter requestIdFilter() { FilterRegistrationBeanRequestIdFilter registration new FilterRegistrationBean(); registration.setFilter(new RequestIdFilter()); registration.addUrlPatterns(/*); registration.setOrder(Ordered.HIGHEST_PRECEDENCE); // 最高优先级 return registration; } }4. 高级应用场景与优化4.1 性能优化避免频繁创建对象在过滤器中使用ThreadLocal缓存常用对象public class PerformanceFilter implements Filter { private static final ThreadLocalSimpleDateFormat dateFormatHolder ThreadLocal.withInitial(() - new SimpleDateFormat(yyyy-MM-dd HH:mm:ss)); Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 使用缓存的对象 String formattedDate dateFormatHolder.get().format(new Date()); response.setHeader(X-Process-Time, formattedDate); chain.doFilter(request, response); } }4.2 安全头设置常见的安全头设置示例public class SecurityHeadersFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse (HttpServletResponse) response; // 防止点击劫持 httpResponse.setHeader(X-Frame-Options, DENY); // XSS保护 httpResponse.setHeader(X-XSS-Protection, 1; modeblock); // 禁止MIME类型嗅探 httpResponse.setHeader(X-Content-Type-Options, nosniff); // CSP策略 httpResponse.setHeader(Content-Security-Policy, default-src self); chain.doFilter(request, response); } }4.3 动态修改请求头有时我们需要在拦截器中修改请求头。由于HttpServletRequest的头部是只读的我们需要使用包装类public class HeaderModificationFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) { Override public String getHeader(String name) { if (User-Agent.equalsIgnoreCase(name)) { return Modified-Agent; } return super.getHeader(name); } Override public EnumerationString getHeaders(String name) { if (User-Agent.equalsIgnoreCase(name)) { return Collections.enumeration(Arrays.asList(Modified-Agent)); } return super.getHeaders(name); } }, response); } }5. 常见问题与解决方案5.1 过滤器不生效的可能原因顺序问题过滤器可能被其他过滤器提前终止解决方案调整Order或setOrder()值URL模式不匹配确保addUrlPatterns()包含你的路径缺少组件扫描确保配置类在组件扫描路径下5.2 拦截器与过滤器的执行顺序典型请求处理流程客户端请求 - Servlet Filter Chain - DispatcherServlet - Interceptor preHandle - Controller - Interceptor postHandle - Interceptor afterCompletion - Servlet Filter Chain - 客户端响应5.3 性能监控实现示例public class MetricsFilter implements Filter { private static final String START_TIME_ATTR startTime; Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long startTime System.currentTimeMillis(); request.setAttribute(START_TIME_ATTR, startTime); chain.doFilter(request, response); long duration System.currentTimeMillis() - startTime; response.setHeader(X-Processing-Time, duration ms); } }5.4 跨域处理的最佳实践虽然可以在过滤器中处理CORS但推荐使用Spring的专用机制Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOrigins(https://trusted.com) .allowedMethods(GET, POST) .allowedHeaders(*) .exposedHeaders(X-Custom-Header) .maxAge(3600); } }6. 测试策略6.1 单元测试过滤器public class CustomHeaderFilterTest { Test public void testHeaderAdded() throws Exception { MockHttpServletRequest request new MockHttpServletRequest(); MockHttpServletResponse response new MockHttpServletResponse(); MockFilterChain chain new MockFilterChain(); new CustomHeaderFilter().doFilter(request, response, chain); assertEquals(value, response.getHeader(X-Custom-Header)); } }6.2 集成测试SpringBootTest AutoConfigureMockMvc public class FilterIntegrationTest { Autowired private MockMvc mockMvc; Test public void testRequestIdHeader() throws Exception { mockMvc.perform(get(/api/test)) .andExpect(header().exists(X-Request-ID)); } }6.3 使用Postman测试发送请求并检查响应头测试不同场景不带请求头的请求带自定义请求头的请求测试安全头是否生效7. 性能考量与最佳实践过滤器链长度每个过滤器都会增加处理时间保持链尽可能短避免阻塞操作不要在过滤器中执行长时间阻塞操作线程安全确保过滤器是线程安全的资源清理在finally块中清理资源如MDC缓存策略对于频繁使用的值考虑使用缓存在最近的一个性能测试中我们发现每增加一个简单的过滤器平均响应时间增加约0.3ms在4核8G的测试环境。当过滤器数量超过10个时性能下降变得明显。因此建议合并相关功能的过滤器将不必要对所有请求生效的过滤器改为只匹配特定路径对于性能关键路径考虑使用更高效的实现方式8. Spring Boot 3.x的新特性在Spring Boot 3.x中过滤器注册有了更简洁的方式Configuration public class FilterConfig { Bean public ServletRegistrationBeanDispatcherServlet dispatcherServletRegistration() { return new ServletRegistrationBean(new DispatcherServlet(), /); } Bean public FilterRegistrationBeanCustomHeaderFilter customHeaderFilter() { return new FilterRegistrationBean(new CustomHeaderFilter()); } }另外Spring Boot 3.x对Servlet API的要求升级到了5.0需要注意兼容性问题。9. 实际项目经验分享在电商项目中实现全链路追踪时我们遇到了几个关键问题异步请求的请求ID传递解决方案使用TaskDecorator包装异步任务Configuration public class AsyncConfig implements AsyncConfigurer { Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setTaskDecorator(new MDCTaskDecorator()); // 其他配置... return executor; } }网关层与微服务的ID传递在网关层生成请求ID通过Feign拦截器传递给下游服务public class FeignRequestInterceptor implements RequestInterceptor { Override public void apply(RequestTemplate template) { String requestId MDC.get(requestId); if (requestId ! null) { template.header(X-Request-ID, requestId); } } }日志系统的集成配置Logback/SLF4J使用MDC中的requestId在ELK等日志系统中建立基于requestId的关联10. 扩展思考更现代的替代方案虽然过滤器和拦截器仍然有效但在新项目中也可以考虑Spring Cloud Gateway过滤器适用于微服务架构的网关层Servlet 3.1的异步处理对于长时间运行的请求Reactive StackWebFlux提供的WebFilter机制Micrometer追踪与分布式追踪系统集成对于全新的Spring Boot 3.x项目WebFlux提供了一种更现代的替代方案Component public class CustomWebFilter implements WebFilter { Override public MonoVoid filter(ServerWebExchange exchange, WebFilterChain chain) { exchange.getResponse().getHeaders().add(X-Custom-Header, value); return chain.filter(exchange); } }这种响应式的方式在处理高并发请求时通常有更好的性能表现。

相关新闻

2026/7/30 10:17:34

Python包管理进阶:使用pip从Git仓库直接安装与配置指南

1. 为什么需要从Git仓库直接安装Python包? 在Python开发中,我们最熟悉的包安装方式无疑是 pip install package-name 。这个命令会从PyPI(Python Package Index)这个官方的软件仓库中,拉取对应名称的包及其依赖&…

2026/7/30 10:17:34

安卓模拟器安装Magisk:安全沙盒中实现系统级Root与模块测试

1. 项目概述:为什么要在模拟器里折腾Magisk?如果你和我一样,是个喜欢在安卓世界里“搞机”的玩家,那么对Magisk一定不陌生。它早已超越了单纯的Root工具,成为了一个强大的模块化框架,能让我们在不破坏系统完…

2026/7/30 10:17:34

百度网盘提取码智能获取:5秒破解资源锁定的终极指南

百度网盘提取码智能获取:5秒破解资源锁定的终极指南 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为百度网盘加密资源而烦恼吗?每次打…

2026/7/30 11:07:36

如何快速解锁Windows家庭版远程桌面完整功能:3分钟实用指南

如何快速解锁Windows家庭版远程桌面完整功能:3分钟实用指南 【免费下载链接】SuperRDP Super RDPWrap 项目地址: https://gitcode.com/gh_mirrors/su/SuperRDP 还在为Windows家庭版无法使用远程桌面而烦恼吗?SuperRDP正是解决这一问题的完美方案&…

2026/7/30 11:07:36

3分钟彻底掌控Windows Edge浏览器:你的系统清理专家

3分钟彻底掌控Windows Edge浏览器:你的系统清理专家 【免费下载链接】EdgeRemover A PowerShell script that correctly uninstalls or reinstalls Microsoft Edge on Windows 10 & 11. 项目地址: https://gitcode.com/gh_mirrors/ed/EdgeRemover 还在为…

2026/7/30 11:02:36

bitbrick_k1集群部署prima_cpp实现分布式大模型推理

1. 项目概述:bitbrick_k1集群部署prima_cpp实现分布式大模型推理最近在bitbrick_k1集群上成功部署了prima_cpp框架,实现了大语言模型的分布式推理。这套方案特别适合需要处理高并发推理请求的企业级场景,比如智能客服、内容生成平台等。bitbr…

2026/7/29 22:32:30

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

2026/7/30 0:01:39

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:01:39

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/29 13:12:43

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…