如何将默认 MessageConverter 设置为 JSON 添加了 jackson-dataformat-xml?
How to set default MessageConverter to JSON with jackson-dataformat-xml added?
我有一个可用的 spring 启动应用程序,它使用 JSON 作为交换数据格式。现在我必须添加一项服务,该服务仅在 xml 中发送他们的数据。我将 jackson-dataformat-xml
添加到我的 pom 中,它运行良好。
@Service
public class TemplateService {
private final RestTemplate restTemplate;
private final String serviceUri;
public TemplateService (RestTemplate restTemplate, @Value("${service.url_templates}") String serviceUri) {
this.restTemplate = restTemplate;
this.serviceUri = serviceUri;
}
public boolean createTemplate(Template template) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity entity = new HttpEntity<>(template, headers);
ResponseEntity<Template> response = restTemplate.exchange(serviceUri, HttpMethod.POST, entity, Template.class);
if (response.getStatusCode().is2xxSuccessful()) {
// do some stuff
return true;
}
return false;
}
}
现在不幸的是,在添加依赖项后,我所有其他 POST 方法默认发送 XML。或者 Content
设置为 application/xml
。但我想在这里设置 JSON。
@Service
public class SomeOtherService{
private final RestTemplate restTemplate;
private final String anotherUri;
public SomeOtherService(RestTemplate restTemplate, @Value("${anotherUri.url}") String anotherUri) {
this.restTemplate = restTemplate;
this.anotherUri = anotherUri;
}
public ComponentEntity doSomething(String projectId, MyNewComponent newComponent) {
ResponseEntity<MyNewComponent> result = this.restTemplate.exchange(anotherUri ,HttpMethod.POST, new HttpEntity<>(newComponent), MyNewComponent.class);
//...
}
}
我没有明确设置 headers,因为有很多 POST 请求,我不想全部更改。有没有办法将 default Content
设置为 JSON?
到目前为止我试过了
- 添加拦截器。但有时我需要 XML。
- 覆盖内容协商
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
- 设置
restTemplate.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
并在我想要 XML 的服务中使用 new RestTemplate()
。
==> 数字 3 确实有效,但感觉有点不对。
我希望在某处设置默认的 Content
类型,以便 JSON 在没有设置的正常情况下使用,而 XML 在我明确设置 Content
到 XML.
感谢您的帮助。
Creating a RestTemplate
bean from the auto-configured RestTemplateBuilder
bean and using it doesn't manifest the situation. This is a test to demonstrate the situation.
我们最终发现,消息转换器的顺序非常重要。 Jackson 似乎将 XML 消息转换器放在 JSON 消息转换器之前。所以我们将 XML 消息转换移到了最后,它起作用了。
@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;
}
您可以按照已接受答案的建议更改消息转换器的顺序,并且效果很好。如果请求没有 Content-Type
header,Jackson 会选择优先级最高的消息转换器。
因此,如果您不想更改 RestTemplate
的配置,您可以将 Content-Type
设置为 application/json
,这将指示 Jackson 使用正确的消息转换器您的要求:
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.ACCEPT, "application/json");
headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
var httpEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
tenantConfig.getTokenUri(), HttpMethod.POST, httpEntity, String.class);
订单由Spring控制。如果您查看 RestTemplate 的默认构造函数,MessageConverter 将根据直接从上面的静态块确定的布尔值添加到列表中(有一个 Spring 属性 被咨询--spring.xml.ignore——控制是否排除加载所有 XML-related 基础设施)。在安装过程中,列表的顺序似乎没有 modify-able。这看起来确实是一个限制,尽管有一个构造函数接受 MessageConverter 列表并使用它。
我有一个可用的 spring 启动应用程序,它使用 JSON 作为交换数据格式。现在我必须添加一项服务,该服务仅在 xml 中发送他们的数据。我将 jackson-dataformat-xml
添加到我的 pom 中,它运行良好。
@Service
public class TemplateService {
private final RestTemplate restTemplate;
private final String serviceUri;
public TemplateService (RestTemplate restTemplate, @Value("${service.url_templates}") String serviceUri) {
this.restTemplate = restTemplate;
this.serviceUri = serviceUri;
}
public boolean createTemplate(Template template) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity entity = new HttpEntity<>(template, headers);
ResponseEntity<Template> response = restTemplate.exchange(serviceUri, HttpMethod.POST, entity, Template.class);
if (response.getStatusCode().is2xxSuccessful()) {
// do some stuff
return true;
}
return false;
}
}
现在不幸的是,在添加依赖项后,我所有其他 POST 方法默认发送 XML。或者 Content
设置为 application/xml
。但我想在这里设置 JSON。
@Service
public class SomeOtherService{
private final RestTemplate restTemplate;
private final String anotherUri;
public SomeOtherService(RestTemplate restTemplate, @Value("${anotherUri.url}") String anotherUri) {
this.restTemplate = restTemplate;
this.anotherUri = anotherUri;
}
public ComponentEntity doSomething(String projectId, MyNewComponent newComponent) {
ResponseEntity<MyNewComponent> result = this.restTemplate.exchange(anotherUri ,HttpMethod.POST, new HttpEntity<>(newComponent), MyNewComponent.class);
//...
}
}
我没有明确设置 headers,因为有很多 POST 请求,我不想全部更改。有没有办法将 default Content
设置为 JSON?
到目前为止我试过了
- 添加拦截器。但有时我需要 XML。
- 覆盖内容协商
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
- 设置
restTemplate.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
并在我想要 XML 的服务中使用 new RestTemplate()
。
==> 数字 3 确实有效,但感觉有点不对。
我希望在某处设置默认的 Content
类型,以便 JSON 在没有设置的正常情况下使用,而 XML 在我明确设置 Content
到 XML.
感谢您的帮助。
Creating a RestTemplate
bean from the auto-configured RestTemplateBuilder
bean and using it doesn't manifest the situation. This is a test to demonstrate the situation.
我们最终发现,消息转换器的顺序非常重要。 Jackson 似乎将 XML 消息转换器放在 JSON 消息转换器之前。所以我们将 XML 消息转换移到了最后,它起作用了。
@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;
}
您可以按照已接受答案的建议更改消息转换器的顺序,并且效果很好。如果请求没有 Content-Type
header,Jackson 会选择优先级最高的消息转换器。
因此,如果您不想更改 RestTemplate
的配置,您可以将 Content-Type
设置为 application/json
,这将指示 Jackson 使用正确的消息转换器您的要求:
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.ACCEPT, "application/json");
headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
var httpEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
tenantConfig.getTokenUri(), HttpMethod.POST, httpEntity, String.class);
订单由Spring控制。如果您查看 RestTemplate 的默认构造函数,MessageConverter 将根据直接从上面的静态块确定的布尔值添加到列表中(有一个 Spring 属性 被咨询--spring.xml.ignore——控制是否排除加载所有 XML-related 基础设施)。在安装过程中,列表的顺序似乎没有 modify-able。这看起来确实是一个限制,尽管有一个构造函数接受 MessageConverter 列表并使用它。