• SpringBoot:MessageConverter自动配置原理


    原理

    我们知道springboot的mvc自动配置在WebMvcAutoConfiguration配置类中

    在该类中,有一个WebMvcAutoConfigurationAdapter类,实现了WebMvcConfigurer接口,并实现了configureMessageConverters方法,该方法就可以添加一些MessageConverter.

    		@Override
    		public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    			this.messageConvertersProvider
    					.ifAvailable((customConverters) -> converters.addAll(customConverters.getConverters()));
    		}
    

    customConverters.getConverters()实现:getConverters方法就是一个普通的get方法,那么converters的初始化可能就在该类创建的时候赋值的。

    image-20210407130546532

    找到该类的构造方法:

    	public HttpMessageConverters(boolean addDefaultConverters, Collection<HttpMessageConverter<?>> converters) {
            //调用getDefaultConverters()方法,并赋值给converters
    		List<HttpMessageConverter<?>> combined = getCombinedConverters(converters,
    				addDefaultConverters ? getDefaultConverters() : Collections.emptyList());
    		combined = postProcessConverters(combined);
    		this.converters = Collections.unmodifiableList(combined);
    	}
    

    getDefaultConverters方法,内部会调用父类的getMessageConverters方法

    image-20210407130858199

    调用本类的addDefaultHttpMessageConverters方法

    image-20210407131013811

    addDefaultHttpMessageConverters方法:这里会配置一些默认的消息转换器,并且从成员变量判断是否需要添加其他的消息转换器。

    protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
    		messageConverters.add(new ByteArrayHttpMessageConverter());
    		messageConverters.add(new StringHttpMessageConverter());
    		messageConverters.add(new ResourceHttpMessageConverter());
    		messageConverters.add(new ResourceRegionHttpMessageConverter());
    		if (!shouldIgnoreXml) {
    			try {
    				messageConverters.add(new SourceHttpMessageConverter<>());
    			}
    			catch (Throwable ex) {
    				// Ignore when no TransformerFactory implementation is available...
    			}
    		}
    		messageConverters.add(new AllEncompassingFormHttpMessageConverter());
    
    		if (romePresent) {
    			messageConverters.add(new AtomFeedHttpMessageConverter());
    			messageConverters.add(new RssChannelHttpMessageConverter());
    		}
    
    		if (!shouldIgnoreXml) {
    			if (jackson2XmlPresent) {
    				Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
    				if (this.applicationContext != null) {
    					builder.applicationContext(this.applicationContext);
    				}
    				messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
    			}
    			else if (jaxb2Present) {
    				messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
    			}
    		}
    
    		if (kotlinSerializationJsonPresent) {
    			messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
    		}
    		if (jackson2Present) {
    			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
    			if (this.applicationContext != null) {
    				builder.applicationContext(this.applicationContext);
    			}
    			messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
    		}
    		else if (gsonPresent) {
    			messageConverters.add(new GsonHttpMessageConverter());
    		}
    		else if (jsonbPresent) {
    			messageConverters.add(new JsonbHttpMessageConverter());
    		}
    
    		if (jackson2SmilePresent) {
    			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();
    			if (this.applicationContext != null) {
    				builder.applicationContext(this.applicationContext);
    			}
    			messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
    		}
    		if (jackson2CborPresent) {
    			Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();
    			if (this.applicationContext != null) {
    				builder.applicationContext(this.applicationContext);
    			}
    			messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
    		}
    	}
    

    成员变量的初始化:这里判断一些场景是否存在,如果存在,则赋值为true,进而导入相关消息转换器

    image-20210407131307771

    自定义消息转换器

    通过上文分析,我们只需要实现WebMvcConfigurer接口,并实现了configureMessageConverters方法,就可以达到自定义消息转换器的目的。

    例如,我不想用jackson了,想用fastjson的消息转换器,我们可以添加fastjson相关的MessageConverter就可以了

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
            List<MediaType> fastMediaTypes = new ArrayList<>();
            fastMediaTypes.add(MediaType.TEXT_HTML);
            fastMediaTypes.add(MediaType.APPLICATION_JSON);
            fastConverter.setSupportedMediaTypes(fastMediaTypes);
            FastJsonConfig fastJsonConfig = new FastJsonConfig();
            fastJsonConfig.setSerializerFeatures(
                    SerializerFeature.WriteMapNullValue,
                    SerializerFeature.WriteNullStringAsEmpty,
                    SerializerFeature.WriteNullListAsEmpty,
                    SerializerFeature.WriteDateUseDateFormat);
            SerializeConfig serializeConfig = SerializeConfig.globalInstance;
            serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
            serializeConfig.put(Long.class, ToStringSerializer.instance);
            serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
            fastJsonConfig.setSerializeConfig(serializeConfig);
            fastConverter.setFastJsonConfig(fastJsonConfig);
            converters.add(fastConverter);
        }
    }
    
    @Data
    public class Person {
        private String userName;
        private Integer age;
        //使用fastjson的注解进行转换
        @JSONField(format = "yyyy-MM-dd")
        private Date birth;
        private Pet pet;
    }
    

    image-20210407140421578

  • 相关阅读:
    javsscript闭包的一种使用场景--沙箱
    toString()方法,与call()方法结合;用来进行数据类型检测
    [学习笔记]数论(二)
    [模板]平面最近点对
    [bzoj1670][Usaco2006 Oct]Building the Moat
    [模板]计算几何(一)
    [日常训练]string
    [bzoj3626][LNOI2014]LCA
    [bzoj2732][HNOI2012]射箭
    [学习笔记]半平面交
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14627424.html
Copyright © 2020-2023  润新知