如何在请求抵达Controller前通过Filter修改请求头?
问题描述
无法在Filter(当作拦截器使用)中修改请求头,希望在请求到达Controller前修改已存在的请求头。
当前Filter实现代码:
public class MyInterceptor implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; HttpServletResponse res = (HttpServletResponse) servletResponse; //something //myHeaders is still present when send a request req.setAttribute("myHeaders","someValue"); chain.doFilter(req, res); } }
期望在Controller中获取修改后的请求头,Controller代码:
@RestController @RequestMapping("/") public class FooClass{ @Autowired private Service service; @GetMapping("/foo") public ResponseEntity<Void> fooApi( @RequestHeader(value = "myHeaders") String myHeaders, ) { service.doSomething(myHeaders); return ResponseEntity.ok().build(); } }
解决方案
原生HttpServletRequest的请求头是不可修改的,必须通过请求包装类改写头信息的获取逻辑,具体操作如下:
- 自定义
HttpServletRequestWrapper子类,重写请求头相关方法,实现修改逻辑:
public class ModifiedHeaderRequestWrapper extends HttpServletRequestWrapper { private final Map<String, String> modifiedHeaders; public ModifiedHeaderRequestWrapper(HttpServletRequest request, Map<String, String> modifiedHeaders) { super(request); this.modifiedHeaders = new HashMap<>(modifiedHeaders); } @Override public String getHeader(String name) { // 优先返回修改后的头值,没有则使用原生请求的头 if (modifiedHeaders.containsKey(name)) { return modifiedHeaders.get(name); } return super.getHeader(name); } @Override public Enumeration<String> getHeaders(String name) { List<String> values = new ArrayList<>(); if (modifiedHeaders.containsKey(name)) { values.add(modifiedHeaders.get(name)); } // 合并原生请求的同名头值(若不需要保留原数值,可删除这段逻辑) Enumeration<String> originalHeaders = super.getHeaders(name); while (originalHeaders.hasMoreElements()) { values.add(originalHeaders.nextElement()); } return Collections.enumeration(values); } @Override public Enumeration<String> getHeaderNames() { Set<String> headerNames = new HashSet<>(Collections.list(super.getHeaderNames())); headerNames.addAll(modifiedHeaders.keySet()); return Collections.enumeration(headerNames); } }
- 修改Filter代码,使用包装后的请求对象传递给后续调用链:
public class MyInterceptor implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; HttpServletResponse res = (HttpServletResponse) servletResponse; // 定义需要修改的请求头键值对 Map<String, String> headersToModify = new HashMap<>(); headersToModify.put("myHeaders", "someValue"); // 包装原生请求 ModifiedHeaderRequestWrapper wrappedRequest = new ModifiedHeaderRequestWrapper(req, headersToModify); // 传递包装后的请求到后续链 chain.doFilter(wrappedRequest, res); } }
- 确保Filter已在Spring容器中正确注册(可通过
@WebFilter注解配合@ServletComponentScan,或者通过配置类手动注册),保证请求会经过该Filter处理。
完成以上操作后,请求到达Controller时,@RequestHeader("myHeaders")就能获取到你修改后的数值。
内容的提问来源于stack exchange,提问作者HittingMyCode
相关产品推荐
相关产品推荐

