Spring RestTemplate消息转换器发帖时的优先级

Spring RestTemplate message converter priority when posting

影响消息转换器优先级的最方便方法是什么 Spring 适用于使用 RestTemplate 进行 POST 时?

用例:我想确保将给定的实体发布为 JSON 而不是例如XML 当我做 restTemplate.postForEntity(url, entity, Void.class).

默认

默认情况下,实体转换为 XML,因为 MappingJackson2XmlHttpMessageConverter 优先于 MappingJackson2HttpMessageConverter。我的应用程序的默认转换器列表似乎是(Spring 扫描类路径以查看可用的内容):

选项 1

您可以像这样 restTemplate.setMessageConverters(Lists.newArrayList(new MappingJackson2HttpMessageConverter())) 为给定的 RestTemplate 实例显式配置消息转换器。如果实例是共享的(例如 Spring bean),这是不方便的,因为在一种情况下您可能需要转换器 X,而在另一种情况下可能需要转换器 Y。

选项 2

您可以明确设置 AcceptContent-Type HTTP headers,在这种情况下 Spring 将使用匹配的消息转换器。缺点是您必须求助于 RestTemplate.exchange 而不是 RestTemplate.postForEntity,这意味着:额外的代码,不太方便。

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
requestHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity requestEntity = new HttpEntity(entity, requestHeaders);
restTemplate.exchange(url, HttpMethod.POST, requestEntity, Void.class);

选项 3

这可能是我要找的:)

根据 Spring javadoc (https://docs.spring.io/spring-framework/docs/current/javadoc-api/index.html?org/springframework/web/client/RestTemplate.html) 你仍然可以使用 postForEntity,

public <T> ResponseEntity<T> postForEntity(java.lang.String url,
                                       @Nullable
                                       java.lang.Object request,
                                       java.lang.Class<T> responseType,
                                       java.util.Map<java.lang.String,?> uriVariables)
                                throws RestClientException
....

request 参数可以是 HttpEntity 以便向请求添加额外的 HTTP headers。

此问题已详细解答

基本上,当您添加下面提到的库时,它会在 MappingJackson2HttpMessageConverter 之前添加 MappingJackson2XmlHttpMessageConverter。因此,Spring 引导假定每个请求都接受 application/XML.

 <dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

为避免这种行为,您可能需要交换两个消息转换器。

示例:

  @Bean
RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
// move XML converter to the end of list
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
for (int i = 0; i < messageConverters.size() -1 ; i++) {
    if (messageConverters.get(i) instanceof MappingJackson2XmlHttpMessageConverter) {
        Collections.swap(messageConverters, i,messageConverters.size() - 1);
    }
}

restTemplate.setMessageConverters(messageConverters);

// add interceptors if necessary
restTemplate.setInterceptors(Collections.singletonList(catalogInterceptior()));
return restTemplate;

}