【问题标题】:Add http headers to RestTemplate by Interceptor or HttpEntity?通过 Interceptor 或 HttpEntity 将 http 标头添加到 RestTemplate?
【发布时间】:2025-12-15 15:15:02
【问题描述】:

如果我有一些静态标头应该应用于 任何 使用RestTemplate 发送的请求:应该如何添加这些标头?

在本例中,我总是希望发送 http 标头 accept=applicaton/json。 (它也可以是任何其他标题,也可以是多个标题)。

1) HttpEntity 直接在发送前:

HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);

ResponseEntity<Rsp> http = restTemplate.postForEntity(host, new HttpEntity<>(req, headers), type);

2)ClientHttpRequestInterceptor:

class MyInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        request.getHeaders().set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
        return execution.execute(request, body);
    }
}

@Bean
public RestTemplateCustomizer customizer() {
    return restTemplate -> restTemplate.getInterceptors().add(new MyInterceptor());
}

然后发帖:

restTemplate.postForEntity(host, req, type);

哪一个比另一个有优势,因此应该被首选?

【问题讨论】:

  • 拦截器通常用于入站请求,对于出站请求,您只需使用一个实用方法即可。
  • @VinayAvasthi 你能举个例子吗?因为,正如上面HttpRequest request 所见,所以我认为它的目的不是针对入站请求。
  • 看来我错了。我不知道。似乎有一个客户端请求的拦截器。我会说拦截器是一种更好的方法,因为所有请求都需要对请求进行类似的添加。

标签: java spring resttemplate spring-web


【解决方案1】:

选项 1 似乎有点难以维护,因为开发人员需要记住每次都这样做。选项2会更好,我只会做以下更改:

你在哪里

restTemplate.getInterceptors().add(new MyInterceptor())

我愿意

List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
if (CollectionUtils.isEmpty(interceptors)) {
    interceptors = new ArrayList<>();
}
interceptors.add(new MyInterceptor());
restTemplate.setInterceptors(interceptors);

这样你就可以初始化列表以防它为空。

另外,要小心,因为有人可以为 bean 设置一个新的拦截器列表而丢失你的。

【讨论】:

  • 拦截器列表默认初始化为空ArrayList
【解决方案2】:

Java 8 Lambda 使用拦截器的方式

new RestTemplateBuilder().interceptors(
   (HttpRequest request, byte[] body, ClientHttpRequestExecution execution) -> {
      request.getHeaders().set(AUTHORIZATION, token);
      return execution.execute(request, body);
   }
).build()

【讨论】:

    【解决方案3】:

    1)HttpEntity直接在发送前:对restTemplate的细粒度控制。它可以工作,但您必须在任何地方重复代码,开发人员可能会忘记它(DRY)

    2) ClientHttpRequestInterceptorRestTemplateCustomizer:从 restTemplateBuilder bean 创建的每个 restTemplate 都会有这个拦截器,适用于一般行为。

    【讨论】:

    • 您知道开发人员是否可以通过使用HttpEntity 额外覆盖RestTemplateCustomizer 设置的标头?还是反过来工作:拦截器覆盖 HttpEntity 标头?