我将spring-boot
与spring-web
和jackson
一起使用。
问题:当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()
已经存在。
答案 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
。
基于环境。
然后将该列表与WebMvcConfigurationSupport
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
您可以看到它只是一个简单的for循环,并且每个转换都要求说“我可以这样做吗?”通过canWrite
方法
选择第一个有效的