问题
I have a working spring boot application that uses JSON as exchange data format. Now I had to add a service that sends their data only in xml. I added jackson-dataformat-xml
to my pom and it worked perfectly.
@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;
}
}
Now unfortunately after adding the dependency all my other POST methods send XML by default. Or the Content
is set to application/xml
.But I'd like to have JSON here.
@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);
//...
}
}
I did not set the headers explicitly as there are lots of POST requests and I don't want to alter them all. Is there a way to set the default Content
to JSON?
So far I tried
- adding an interceptor. But sometimes I need to have XML.
- Overriding content negotiation
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
- setting
restTemplate.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
and using a new RestTemplate()
in the service where I want to have XML.
==> Number 3 actually works, but feels kind of wrong.
I was expecting to set the default Content
type somewhere so that JSON is used in normal cases where nothing is set and XML where I explicitly set the Content
to XML.
Thanks for any help.
回答1:
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.
回答2:
What we ultimately found out, is that the the order of the message converters is highly important. Jackson seems to place the XML message converter before the JSON message converter. So we moved the XML message convert to the end and it worked.
@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;
}
来源:https://stackoverflow.com/questions/57706610/how-to-set-default-messageconverter-to-json-with-jackson-dataformat-xml-added