最近在尝试搭建springboot+dubbo+shiro基于注解的一个项目,突发奇想一想把消息转换器从jackson换成fastjson,因而就开始了折腾之路.java
轻车熟路的去自定了一个SpringMvcConfigure
去继承WebMvcConfigurerAdapter
,而后就发现这个WebMvcConfigurerAdapter
居然过期了?what?点进去看源码:web
/** * An implementation of {@link WebMvcConfigurer} with empty methods allowing * subclasses to override only the methods they're interested in. * * @author Rossen Stoyanchev * @since 3.1 * @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made * possible by a Java 8 baseline) and can be implemented directly without the * need for this adapter */ @Deprecated public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {}
能够看到从spring5.0开始就被@Deprecated,原来是java8中支持接口中有默认方法,因此咱们如今能够直接实现WebMvcConfigurer
,而后选择性的去重写某个方法,而不用实现它的全部方法.spring
因而就实现了WebMvcConfigurer
:json
@Configuration public class SpringMvcConfigure implements WebMvcConfigurer { /** * 配置消息转换器 * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); //自定义配置... FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString, /*SerializerFeature.WriteMapNullValue,*/ SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect); fastJsonHttpMessageConverter.setFastJsonConfig(config); converters.add(fastJsonHttpMessageConverter); } }
本觉得这样子配置就能够完事儿,可是诡异的事情发生了,我明明注释了SerializerFeature.WriteMapNullValue
,但是返回的json中仍然有为null
的字段,而后我就去com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter
中的write
和writeInternal
打了断点,再次执行,居然什么都没有发生,根本没有走这两个方法,因而在自定义的SpringMvcConfigure
中configureMessageConverters
方法内打了断点,想看看这个方法参数converters
里边到底有什么:api
看到这里就想到,确定是我本身添加的fastjson在后边,因此没有生效,因此就加了如下代码:springboot
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters = converters.stream() .filter((converter)-> !(converter instanceof MappingJackson2HttpMessageConverter)) .collect(Collectors.toList()); FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); //自定义配置... FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString, /*SerializerFeature.WriteMapNullValue,*/ SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect); fastJsonHttpMessageConverter.setFastJsonConfig(config); converters.add(fastJsonHttpMessageConverter); }
居然尚未生效,后来开始追踪,开始方法是从org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
类中的一个bean配置:mvc
@Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); adapter.setContentNegotiationManager(mvcContentNegotiationManager()); //就是从这里开始设置converters的,而后从这里一路追踪下去. adapter.setMessageConverters(getMessageConverters()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); adapter.setCustomArgumentResolvers(getArgumentResolvers()); adapter.setCustomReturnValueHandlers(getReturnValueHandlers()); if (jackson2Present) { adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice())); adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice())); } AsyncSupportConfigurer configurer = new AsyncSupportConfigurer(); configureAsyncSupport(configurer); if (configurer.getTaskExecutor() != null) { adapter.setTaskExecutor(configurer.getTaskExecutor()); } if (configurer.getTimeout() != null) { adapter.setAsyncRequestTimeout(configurer.getTimeout()); } adapter.setCallableInterceptors(configurer.getCallableInterceptors()); adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors()); return adapter; }
getMessageConverters()
方法:app
protected final List<HttpMessageConverter<?>> getMessageConverters() { if (this.messageConverters == null) { this.messageConverters = new ArrayList<>(); configureMessageConverters(this.messageConverters);//进入这一步 if (this.messageConverters.isEmpty()) { addDefaultHttpMessageConverters(this.messageConverters); } extendMessageConverters(this.messageConverters); } return this.messageConverters; }
org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
:ide
@Override protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) { this.configurers.configureMessageConverters(converters); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { for (WebMvcConfigurer delegate : this.delegates) { delegate.configureMessageConverters(converters); } }
this.delegates包含了springboot的一个默认配置类类:org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
里边有一个参数this
private final HttpMessageConverters messageConverters;
for循环里的delegate.configureMessageConverters(converters)
调用了WebMvcAutoConfiguration
中的configureMessageConverters
方法:
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.addAll(this.messageConverters.getConverters()); }
执行完这个后,就给converters
中添加了10
个转换器了,就是上图中的10个.this.delegates
中还有一个就是咱们自定义的那个,执行完后,在咱们自定义的那个SpringMvcConfigure
发现我添加的fastjson添加进去了,可是org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.getMessageConverters()
,发现converters并无发现咱们添加进去的FastJsonHttpMessageConverter
,这时忽然又想起来:java8的stream api每次都是生成一个新的对象,因此致使converters已经不是传递过来的那个converters的引用了(这里也证实了java是值传递,不是引用传递).
因而再次改变那个lambda表达式为普通的加强for循环:
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { /*converters = converters.stream(). filter((converter)-> !(converter instanceof MappingJackson2HttpMessageConverter)) .collect(Collectors.toList());*/ for (HttpMessageConverter<?> converter : converters) { if (converter instanceof MappingJackson2HttpMessageConverter){ converters.remove(converter); } } FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); //自定义配置... FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString, /*SerializerFeature.WriteMapNullValue,*/ SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect); fastJsonHttpMessageConverter.setFastJsonConfig(config); converters.add(fastJsonHttpMessageConverter); }
再次运行,wtf?报错了:ConcurrentModificationException
,原来使用for循环遍历过程当中不能进行remove操做,因而换成Iterator
:
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { /*converters = converters.stream() .filter((converter)-> !(converter instanceof MappingJackson2HttpMessageConverter)) .collect(Collectors.toList()); for (HttpMessageConverter<?> converter : converters) { if (converter instanceof MappingJackson2HttpMessageConverter){ converters.remove(converter); } }*/ Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); while(iterator.hasNext()){ HttpMessageConverter<?> converter = iterator.next(); if(converter instanceof MappingJackson2HttpMessageConverter){ iterator.remove(); } } FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); //自定义配置... FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString, /*SerializerFeature.WriteMapNullValue,*/ SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect); fastJsonHttpMessageConverter.setFastJsonConfig(config); converters.add(fastJsonHttpMessageConverter); }
再次运行,我去,终于解决了,先是删除MappingJackson2HttpMessageConverter
,而后添加FastJsonHttpMessageConverter
,可是不是到为何进过一系列操做后,MappingJackson2HttpMessageConverter
仍是添加进去了,可是因为FastJsonHttpMessageConverter
在MappingJackson2HttpMessageConverter
以前添加,因此对结果不影响.至此,解决了这个问题.
若有不正确的地方还请指出,谢谢.