RestTemplateBuilder中重复的MessageConverters?

问题描述 投票:0回答:1

我正在使用spring-bootspring-webjackson

问题:当弹簧自动初始化RestTemplate时,构造函数会收到一些重复的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

因为我自己没有初始化任何消息转换器:为什么应用程序上下文根本包含重复的转换器,然后添加到resttemplate?

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

例如:第一个ObjectMapperMappingJackson2HttpMessageConverter比第二个包含更多的registeredModuleTypes [Jdk8Module, JavaTimeModule, ParamterNamesModule, JsonComponentModule, GeoModule](仅包含:[Jdk8Module, JavaTimeModule])。

那有意义吗?

它通过RestTemplateAutoConfiguration.restTemplateBuilder()实例化,所有重复的MessageConverters已经存在。

java spring spring-boot jackson spring-web
1个回答
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(s)。 基于环境。

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(s)通过HttpMessageConvertersAutoConfiguration找到并实例化,其文档是

HttpMessageConverters的自动配置。

该课程本身就是一个StringHttpMessageConverter

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

比,它进口杰克逊或Gson自动配置

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

这就是那些基于环境的那些被“加总”到预定义的那些。


Spring不会被重复项混淆,因为它只需要第一个兼容的东西。 看看如何选择HttpMessageConverter

enter image description here

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

enter image description here

选择第一个有效期。

© www.soinside.com 2019 - 2024. All rights reserved.