Spring Boot RestController请求/响应头修改及拦截扩展方案问询
Hey there! Since you're new to Spring Boot and the Servlet ecosystem, let me break down exactly how to implement header modification before entering a RestController and after it finishes processing—plus how to target specific controllers with a custom annotation, just like you asked.
1. Use HandlerInterceptor (Your Go-To Tool)
HandlerInterceptor is exactly what you need here: it lets you hook into the request lifecycle at key points, and we’ll focus on two that fit your use case perfectly:
preHandle: Runs before the controller method executes (ideal for modifying request headers)postHandle: Runs after the controller method finishes processing (perfect for tweaking response headers)
First, though, we need a way to tell Spring which controllers or methods should trigger this logic—so let’s build a custom annotation to mark them.
2. Create a Custom Marker Annotation
This annotation will act as a flag for the controllers/methods you want to apply header modifications to. You can even add parameters later for easy extension!
import java.lang.annotation.*; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ModifyHeaders { // Example future extension: Add default header values directly in the annotation // String[] customRequestHeaders() default {}; // String[] customResponseHeaders() default {}; }
3. Implement the HandlerInterceptor
Here’s where the actual header modification logic lives. A critical note: the native HttpServletRequest doesn’t let you modify headers directly, so we’ll use a wrapper class to get around that limitation.
3.1 Request Wrapper for Editable Headers
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.util.HashMap; import java.util.Map; public class ModifiedRequestWrapper extends HttpServletRequestWrapper { private final Map<String, String> customHeaders; public ModifiedRequestWrapper(HttpServletRequest request) { super(request); this.customHeaders = new HashMap<>(); } public void addOrUpdateHeader(String name, String value) { customHeaders.put(name, value); } @Override public String getHeader(String name) { // Check our custom headers first, fall back to original if not found String customValue = customHeaders.get(name); return customValue != null ? customValue : super.getHeader(name); } }
3.2 The Interceptor Class
import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HeaderModifyingInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // Check if the target controller/method has our @ModifyHeaders annotation if (isTargetAnnotated(handler)) { // Wrap the request to make headers editable ModifiedRequestWrapper wrappedRequest = new ModifiedRequestWrapper(request); // Example: Add/modify a request header wrappedRequest.addOrUpdateHeader("X-Custom-Request-Tag", "Processed-By-Interceptor"); // Replace the original request with our wrapped version request = wrappedRequest; } return true; // Allow the request to continue to the controller } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, org.springframework.web.servlet.ModelAndView modelAndView) throws Exception { // Check if the target controller/method has our @ModifyHeaders annotation if (isTargetAnnotated(handler)) { // Modify response headers directly (no wrapper needed here!) response.setHeader("X-Custom-Response-Tag", "Modified-After-Controller"); // You can also add multiple headers or overwrite existing ones response.addHeader("X-Processing-Time", System.currentTimeMillis() - request.getSession().getCreationTime() + "ms"); } } // Helper method to check for our annotation on the controller or method private boolean isTargetAnnotated(Object handler) { if (handler instanceof org.springframework.web.method.HandlerMethod) { org.springframework.web.method.HandlerMethod handlerMethod = (org.springframework.web.method.HandlerMethod) handler; // Check method-level annotation first if (handlerMethod.getMethodAnnotation(ModifyHeaders.class) != null) { return true; } // Fall back to checking the controller class return handlerMethod.getBeanType().isAnnotationPresent(ModifyHeaders.class); } return false; } }
4. Register the Interceptor with Spring Boot
To make Spring aware of our interceptor, we need to register it in a configuration class that implements WebMvcConfigurer:
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 WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HeaderModifyingInterceptor()); // Optional: Restrict the interceptor to specific paths if needed // registry.addInterceptor(new HeaderModifyingInterceptor()).addPathPatterns("/api/**"); } }
5. Apply the Annotation to Your Controllers
Now just add the @ModifyHeaders annotation to any RestController or method you want to apply header modifications to:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @ModifyHeaders // Applies header logic to all methods in this controller public class ExampleController { @GetMapping("/hello") public String sayHello() { return "Hello from annotated controller!"; } // Or apply to a single method only @GetMapping("/greet") @ModifyHeaders public String sendGreeting() { return "Greetings from annotated method!"; } }
6. Extending the Functionality Later
Since you mentioned expanding this feature down the line, here are some easy ways to scale:
- Add parameters to the
@ModifyHeadersannotation (likerequestHeadersorresponseHeaders) to let users specify header key-value pairs directly in the annotation - Create multiple interceptor implementations for different header strategies (e.g., authentication headers, logging headers) and use the annotation to select which one to use
- Add validation or logging in the interceptor to track when headers are modified for debugging purposes
内容的提问来源于stack exchange,提问作者Myles

