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

Spring Boot拦截器preHandle方法中添加自定义请求头的解决方案咨询

Solution: Adding Custom Request Headers in Spring HandlerInterceptor

Alright, I’ve run into this exact issue before—trying to add a custom request header in a Spring HandlerInterceptor when the original request doesn’t have it, and you can’t modify the controller code that depends on it. Let’s break down how to fix this properly.

The core problem here is that the default HttpServletRequest implementation (like Tomcat’s Request class) doesn’t let you directly modify request headers—they’re treated as immutable once the request is received. To get around this, we need to wrap the original request in a custom HttpServletRequestWrapper that overrides header-related methods to include our custom value.

Step 1: Create a Custom Request Wrapper

First, we’ll build a wrapper class that lets us add custom headers while preserving all original request data:

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.util.*;

public class CustomHeaderRequestWrapper extends HttpServletRequestWrapper {
    private final Map<String, String> customHeaders;

    public CustomHeaderRequestWrapper(HttpServletRequest request) {
        super(request);
        this.customHeaders = new HashMap<>();
    }

    // Method to add our custom header
    public void addHeader(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);
        if (customValue != null) {
            return customValue;
        }
        return super.getHeader(name);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        // Combine custom header with original headers
        List<String> headerValues = new ArrayList<>();
        if (customHeaders.containsKey(name)) {
            headerValues.add(customHeaders.get(name));
        }
        Enumeration<String> originalHeaders = super.getHeaders(name);
        while (originalHeaders.hasMoreElements()) {
            headerValues.add(originalHeaders.nextElement());
        }
        return Collections.enumeration(headerValues);
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        // Combine custom header names with original ones
        Set<String> allHeaderNames = new HashSet<>(customHeaders.keySet());
        Enumeration<String> originalNames = super.getHeaderNames();
        while (originalNames.hasMoreElements()) {
            allHeaderNames.add(originalNames.nextElement());
        }
        return Collections.enumeration(allHeaderNames);
    }
}

Step 2: Update Your HandlerInterceptor

Now, modify your KeyTaskInterceptor to wrap the request with our custom wrapper when your condition is met, and update the request context so downstream components (like your controller) use the wrapped version:

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;

public class KeyTaskInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (/* Your custom condition here */) {
            // Wrap the original request and add the custom header
            CustomHeaderRequestWrapper wrappedRequest = new CustomHeaderRequestWrapper(request);
            wrappedRequest.addHeader("KeyCode", "Your-Custom-Value-Here");

            // Update the request context to use our wrapped request
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                attributes.setRequest(wrappedRequest);
            }
        }
        return true;
    }
}

Alternative: Use a Filter (More Reliable for Request Wrapping)

If you’re open to switching from an interceptor to a filter, this is often a more straightforward approach. Filters run earlier in the request lifecycle and are designed to modify request/response objects directly:

1. Create the Filter

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;

public class KeyTaskFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        if (/* Your custom condition here */) {
            CustomHeaderRequestWrapper wrappedRequest = new CustomHeaderRequestWrapper(request);
            wrappedRequest.addHeader("KeyCode", "Your-Custom-Value-Here");
            // Pass the wrapped request to the next filter/controller
            filterChain.doFilter(wrappedRequest, servletResponse);
        } else {
            // Use original request if condition isn't met
            filterChain.doFilter(request, servletResponse);
        }
    }

    // Optional: Implement init() and destroy() if needed
}

2. Register the Filter (Spring Boot Example)

In Spring Boot, you can register the filter using a FilterRegistrationBean:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<KeyTaskFilter> keyTaskFilter() {
        FilterRegistrationBean<KeyTaskFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new KeyTaskFilter());
        // Specify URL patterns to apply this filter to
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
}

Why This Works

The custom wrapper overrides all the methods that controllers use to access request headers (getHeader, getHeaders, getHeaderNames). When your controller looks for the KeyCode header, it will first check our custom map and return the value we added, just like if it was sent by the frontend.


内容的提问来源于stack exchange,提问作者xarqt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 02:27:37