最近在嘗試搭建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
以前添加,因此對結果不影響.至此,解決了這個問題.
若有不正確的地方還請指出,謝謝.