(HttpServletRequest)req.setAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, Collections.unmodifiableSet(Arrays.asList(MediaType.TEXT_XML).stream().collect(Collectors.toSet())));
这里主要的作用在于,当使用全局的exception handler的时候,是没法写consumer注解的,也就没法指定到底对exception处理的时候,返回的序列化,是采用xml还是jason。此时,就需要在exception handler上,写如上的话,来控制exception返回model的序列化方式。
附:
之前写框架代码的时候,会遇到有点奇怪的事情。有时候全局exception返回的对象是用xml格式返回的。有的时候又是采用jason形式返回的。因此为了处理,采用了上面写到的情况处理。但是为什么这样,没有时间仔细研究,这次研究了下。是这样的:
对pom的配置是这样的,如果加入了:
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
会引入jason2xml相关的converter。验证代码如下:
@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = {WebConfig.class})
public class WebConfig implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List> converters) {
// TODO Auto-generated method stub
for(HttpMessageConverter> c : converters){
if(c instanceof MappingJackson2XmlHttpMessageConverter){
((MappingJackson2XmlHttpMessageConverter)c).getObjectMapper().setTimeZone(TimeZone.getTimeZone("GMT+8"));
}
}
WebMvcConfigurer.super.extendMessageConverters(converters);
}
}
在converters处打断点,可以看到如果没有相关的xml的pom时。所有的converters有8个。能够和返回的object相关的
只有一个,就是MappingJackson2HttpmessageConverter.
当存在 此pom的时候,对应的converters有8个,能够和返回的object相关的除了MappingJackson2HttpmessageConverter还有
MappingJackson2XmlHttpMessageConverter。而且,MappingJackson2XmlHttpMessageConverter在converters的list排序
还是在MappingJackson2HttpmessageConverter之前。
2.相关选择哪种converter来序列化返回object。对应的代码在:
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(T, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)
中有这么一句:
List
该方法具体实现是这样的
@SuppressWarnings("unchecked")
protected List getProducibleMediaTypes(HttpServletRequest request, Class> valueClass, Type declaredType) {
Set mediaTypes = (Set) request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
if (!CollectionUtils.isEmpty(mediaTypes)) {
return new ArrayList(mediaTypes);
}
else if (!this.allSupportedMediaTypes.isEmpty()) {
List result = new ArrayList();
for (HttpMessageConverter> converter : this.messageConverters) {
if (converter instanceof GenericHttpMessageConverter && declaredType != null) {
if (((GenericHttpMessageConverter>) converter).canWrite(declaredType, valueClass, null)) {
result.addAll(converter.getSupportedMediaTypes());
}
}
else if (converter.canWrite(valueClass, null)) {
result.addAll(converter.getSupportedMediaTypes());
}
}
return result;
}
else {
return Collections.singletonList(MediaType.ALL);
}
}
上面就是为了确认哪些messageConverter是和返回的content-type可以相容,序列化对应的返回值的。
当没有引入xml-dataformat对应的pom时,只有MappingJackson2HttpmessageConverter和返回的value对象相适应。
因此就返回成了json。
当存在MappingJackson2XmlHttpMessageConverter与MappingJackson2HttpmessageConverter两种converter的时候。
两者都可以序列化object。但是因为MappingJackson2XmlHttpMessageConverter在converter list里面的排序先于
MappingJackson2HttpmessageConverter。因此对于异常,首选会选中MappingJackson2XmlHttpMessageConverter
进行异常对象的序列化。
因此导致引入xml相关的pom配置后,异常的response返回就都是xml形式了。
如果想要改变这种规则,针对不同的url请求或content-type设置不同的返回形式(json\xml?)。就需要使用最开始提到的
(HttpServletRequest)req.setAttribute方法。具体源码代码这里就不粘贴了。