RestTemplateBuilder中有重复的MessageConverters吗?

时间:2019-04-04 13:55:22

标签: java spring spring-boot jackson spring-web

我将spring-bootspring-webjackson一起使用。

问题:当RestTemplate由spring自动初始化时,构造函数会收到一些重复的MessageConverters

org.springframework.http.converter.ByteArrayHttpMessageConverter@6a1b4854,
org.springframework.http.converter.StringHttpMessageConverter@2d5b549b, 
org.springframework.http.converter.StringHttpMessageConverter@6a175162, 
org.springframework.http.converter.ResourceHttpMessageConverter@7641c4e7, 
org.springframework.http.converter.ResourceRegionHttpMessageConverter@650a0b50, 
org.springframework.http.converter.xml.SourceHttpMessageConverter@55e3b64d, 
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@52f71d2, 
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@f3c27e9, 
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@7d31fb6c, 
org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter@701c413, 
org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter@48543f11

您看到,有3个重复项:

StringHttpMessageConverter
MappingJackson2HttpMessageConverter
MappingJackson2XmlHttpMessageConverter

由于我本人未初始化任何消息转换器:为什么应用程序上下文中完全包含重复的转换器,然后将它们添加到剩余模板中?

特别是:如果某些转换器重复出现(但配置不同),这不会混淆(反)序列化吗?

例如:第一个ObjectMapper的{​​{1}}包含的MappingJackson2HttpMessageConverter registeredModuleTypes比第二个{只包含[Jdk8Module, JavaTimeModule, ParamterNamesModule, JsonComponentModule, GeoModule])。

>

这有意义吗?

通过[Jdk8Module, JavaTimeModule]实例化,所有重复的RestTemplateAutoConfiguration.restTemplateBuilder()已经存在。

1 个答案:

答案 0 :(得分:1)

罪魁祸首在这里,HttpMessageConverters

public HttpMessageConverters(boolean addDefaultConverters,
        Collection<HttpMessageConverter<?>> converters) {
    List<HttpMessageConverter<?>> combined = getCombinedConverters(converters,
            addDefaultConverters ? getDefaultConverters() : Collections.emptyList());
    combined = postProcessConverters(combined);
    this.converters = Collections.unmodifiableList(combined);
}

具体来说,此行(已格式化)

List<HttpMessageConverter<?>> combined = 
       getCombinedConverters(
           converters, 
           addDefaultConverters 
               ? getDefaultConverters() 
               : Collections.emptyList());

converters集合包含扫描的HttpMessageConverter
基于环境。

enter image description here

然后将该列表与WebMvcConfigurationSupport

提供的默认一起加入

enter image description here

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
    private static final boolean romePresent;
    private static final boolean jaxb2Present;
    private static final boolean jackson2Present;
    private static final boolean jackson2XmlPresent;
    private static final boolean jackson2SmilePresent;
    private static final boolean jackson2CborPresent;
    private static final boolean gsonPresent;
    private static final boolean jsonbPresent;
    ...

WebMvcConfigurationSupport个州提供相关文件

  

此类注册...   ...的范围为HttpMessageConverters,具体取决于类路径上可用的第三方库。

找到扫描的HttpMessageConverter,并通过HttpMessageConvertersAutoConfiguration实例化,其文档为

  

HttpMessageConverters的自动配置。

该类本身暴露了StringHttpMessageConverter

@Bean
@ConditionalOnMissingBean
public StringHttpMessageConverter stringHttpMessageConverter() {
    StringHttpMessageConverter converter = new StringHttpMessageConverter(
            this.properties.getCharset());
    converter.setWriteAcceptCharset(false);
    return converter;
}

然后,它导入Jackson或Gson自动配置

@Import({ 
    JacksonHttpMessageConvertersConfiguration.class
    GsonHttpMessageConvertersConfiguration.class,
    JsonbHttpMessageConvertersConfiguration.class 
})

这就是将那些基于环境的“汇总”到预先定义的环境的方式。


Spring不会因为重复而感到困惑,因为它只需要兼容的第一个。
查看如何选择HttpMessageConverter

enter image description here

您可以看到它只是一个简单的for循环,并且每个转换都要求说“我可以这样做吗?”通过canWrite方法

enter image description here

选择第一个有效的