如何控制全局异常处理器返回异常的格式(xml还是json)?

(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 producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);

该方法具体实现是这样的

	@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方法。具体源码代码这里就不粘贴了。

你可能感兴趣的:(如何控制全局异常处理器返回异常的格式(xml还是json)?)