You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot RestController请求/响应头修改及拦截扩展方案问询

Solution for Modifying Request/Response Headers in Spring Boot RestControllers

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 @ModifyHeaders annotation (like requestHeaders or responseHeaders) 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:25:17