问题描述
引用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)
}
网友评论