Spring HandleInterceptor设置Response Header无效的问题解决
问题:Spring Interceptor无法正确设置响应头ResponseId
代码实现
1. 测试Controller
@RestController public class SpringController { @PostMapping(value="/test") public String test(){ return "test"; } }
2. 自定义Interceptor
import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @Component public class ControllerInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Pre-handle"); System.out.println(request.getHeader("RequestId")); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { response.setHeader("ResponseId", "2"); System.out.println("Post-handle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { response.addHeader("ResponseId", "2"); System.out.println(response.getHeader("ResponseId")); System.out.println("After completion"); } }
3. Interceptor配置类
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class ControllerInterceptorAppConfig implements WebMvcConfigurer{ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new ControllerInterceptor()); } }
现象
在Postman中添加RequestId:1请求头后,终端打印:
Pre-handle 1 Post-handle null After completion
响应头ResponseId未出现在Postman的响应中,且终端打印null。
解决方案
问题原因
- afterCompletion阶段无法修改响应头:
*afterCompletion*方法是在响应已经提交给客户端之后执行的,此时响应输出流已关闭,无法修改响应头,调用addHeader不会生效;同时响应提交后调用getHeader也无法获取已设置的头信息,所以打印出null。 - Interceptor实例创建不规范:配置类中手动
new ControllerInterceptor(),但该类已标注@Component,手动new会导致实例脱离Spring容器管理(虽非本次头不生效的直接原因,但不符合规范)。
修复步骤
移除afterCompletion中对响应头的操作:仅在
*postHandle*方法中设置响应头,该方法在处理器执行完成、响应尚未提交给客户端之前执行,此时修改响应头有效。
修改后的Interceptor:@Component public class ControllerInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Pre-handle"); System.out.println(request.getHeader("RequestId")); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { response.setHeader("ResponseId", "2"); System.out.println("Post-handle"); // 可在此处打印验证头信息 System.out.println(response.getHeader("ResponseId")); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("After completion"); // 禁止在此操作响应头 } }规范Interceptor的注入方式:在配置类中通过依赖注入获取
ControllerInterceptor实例,避免手动new:import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class ControllerInterceptorAppConfig implements WebMvcConfigurer{ private final ControllerInterceptor controllerInterceptor; // 构造方法注入 public ControllerInterceptorAppConfig(ControllerInterceptor controllerInterceptor) { this.controllerInterceptor = controllerInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(controllerInterceptor); } }
验证
修改完成后重启服务,用Postman发送请求,即可在响应头中看到ResponseId:2,终端也会打印正确的头信息。
内容的提问来源于stack exchange,提问作者TSSK
相关产品推荐
相关产品推荐

