在 RestController 中处理之前将 RequestParams 复制到 RequestHeaders

Copy RequestParams to RequestHeaders before handling in RestController

为了替换遗留系统而不破坏界面,我正在寻找一种方法来实现以下场景:

如果 REST 客户端没有设置特定的 HTTP header(applicationId)而是将其作为 query-paramter(也称为 RequestParameter)发送,则该值应作为Spring Boot RestController 中的方法参数。

当前方法如下所示:

@RequestMapping(value = "/something", method = RequestMethod.GET)
    public void doSomething(@RequestHeader("applicationId") String applicationId) { }

我认为可能有两种可能的方式:

  1. 注释方法以某种方式将query-parameter或header映射到方法参数
  2. 写一个 Interceptor 来读取请求的所有 query-parameters 并用它们的值设置 non-existing headers。这样一来,方法就完全不用动了。

在这两种方式中,我不确定如何实现它们(甚至不知道 1. 是否可行)。我尝试使用自己的 HandlerInterceptor,它在 preHandle 中读取 query-params(成功),但无法在将请求转发到 RestController 之前在请求中设置 header。

写一个 Filter,用 HttpServletRequestWrapper 包装传入的请求。这个包装器应该覆盖 getHeader 方法。

public ParameterToHeaderWrappingRequestFilter extends OncePerRequestFilter {

    protected void doFilterInternal(
        HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        filterChain.doFilter(new ParameterToHeaderWrappingRequest(request), response, filterChain);
    }
}

在您的 Spring 引导应用程序中将此过滤器注册为 @Bean,它将自动应用。

public class ParameterToHeaderWrappingRequest extends HttpServletRequestWrapper {

    public String getHeader(String name) {
        String header = super.getHeader(name);
        if (header == null) {
            header = getParameter(name);
        }
        return header;
    }
}

类似的东西应该可以解决问题。根据您的需要,您可能 want/need 覆盖一些额外的基于 header 的方法,并且您可能希望限制 header 的数量以使用参数覆盖。

您的其余代码现在可以按原样编写。