如何在添加了 jackson-dataformat-xml 的情况下将默认 MessageConverter 设置为 JSON?

Cli*_*ira 5 java spring-boot jackson-dataformat-xml jackson-databind

我有一个使用 JSON 作为交换数据格式的工作 Spring Boot 应用程序。现在我不得不添加一个仅以 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在不幸的是,在添加依赖项后,我所有其他 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);
    //...
    }
}

Run Code Online (Sandbox Code Playgroud)

我没有明确设置标头,因为有很多 POST 请求,我不想全部更改它们。有没有办法将默认设置 Content为 JSON?

到目前为止我试过

  1. 添加拦截器。但有时我需要有 XML。
  2. 覆盖内容协商
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.defaultContentType(MediaType.APPLICATION_JSON);
    }
Run Code Online (Sandbox Code Playgroud)
  1. 环境
restTemplate.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
Run Code Online (Sandbox Code Playgroud)

new RestTemplate()在我想要 XML 的服务中使用 a 。

==> 3 号确实有效,但感觉有点不对。

我希望在Content某处设置默认类型,以便在没有设置任何内容的正常情况下使用 JSON,而在我显式设置Content为 XML 的情况下使用XML。

谢谢你的帮助。

Cli*_*ira 6

我们最终发现,消息转换器的顺序非常重要。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;
}
Run Code Online (Sandbox Code Playgroud)

  • 是杰克逊决定还是春天决定?这应该可以通过 spring 属性直接配置 (2认同)