Springboot引用jackson-dataformat-x

2020-12-16  本文已影响0人  百恼神烦

问题描述

引用jackson-dataformat-xml后,原本返回json的接口全部返回了xml,除了前端调用时因有加特定的请求头而可以返回json外,尤其是后端服务间调用时全部返回了xml,导致json反序列化失败。

解决过程

让xml解析顺序重新排序

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 重新加入Jackson解析json的类,让其顺序排在xml解析的前面
        converters.add(new MappingJackson2HttpMessageConverter());
    }
}

注意这里千万不能再加个@EnableWebMvc,会导致之前注入的Converter全部失效,参照这里
然而这并不一直能解决问题,实际中发现有些接口能调整回来,有些不能,原因大概是用谷歌浏览器访问时,它的Accept如果没有指定,默认xml会排在前面申请;还有服务间的通信,由于之前没有指定还是返回了xml。服务间通信是直接使用RestTemplate的,直接new,为了方便管理,改为注入一个写了Accept头的对象。
实现一个ClientHttpRequestInterceptor,便于加入Header配置

public class HeaderInterceptor implements ClientHttpRequestInterceptor {
    private final Map<String,String> headers = new HashMap<>();

    public void setHeader(String key,String value){
        headers.put(key,value);
    }


    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        for(String k : headers.keySet()){
            request.getHeaders().set(k,headers.get(k));
        }
        return execution.execute(request, body);
    }
}

注入RestTemplate

    @Bean
    public RestTemplate restTemplate(){
        RestTemplate restTemplate = new RestTemplate();
        HeaderInterceptor interceptor = new HeaderInterceptor();
        interceptor.setHeader("Accept","application/json");
        restTemplate.setInterceptors(Arrays.asList(interceptor));
        return restTemplate;
    }

顺便提一句,@ResqustMapping(produces="application/json") 也是可以的,然而太麻烦,反正前端在请求时会指定content-type,这个似乎会暗示返回结果,因此也能稳定返回json格式

牢骚

我这边发现配置Media解析顺序用处不大,尤其是用谷歌浏览器时,它的Accept拿到就是xml排前面的,因此下面的设置没什么用

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.defaultContentType(xxx)
    }
上一篇下一篇

猜你喜欢

热点阅读