RestTemplateBuilder 中的重复 MessageConverters?
Duplicate MessageConverters in RestTemplateBuilder?
我将 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
因为我自己没有初始化任何消息转换器:为什么应用程序上下文根本包含重复的转换器,然后将它们添加到 resttemplate 中?
特别是:如果某些转换器出现重复(但配置不同),这不会混淆(反)序列化吗?
例如:第一个 MappingJackson2HttpMessageConverter
的 ObjectMapper
比第二个(仅包含:[Jdk8Module, JavaTimeModule]
)包含更多 registeredModuleTypes
[Jdk8Module, JavaTimeModule, ParamterNamesModule, JsonComponentModule, GeoModule]
。
这有意义吗?
它是通过 RestTemplateAutoConfiguration.restTemplateBuilder()
实例化的,所有重复的 MessageConverters
都已经存在。
罪魁祸首在这里,在 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)。
基于环境。
然后该列表与 默认值 由 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
状态
的文档
This class registers ...
... a range of HttpMessageConverters
depending on the third-party libraries available on the classpath.
扫描的 HttpMessageConverter
(s) 是通过 HttpMessageConvertersAutoConfiguration
找到并实例化的,其文档是
Auto-configuration for HttpMessageConverters
.
那个 class 自己暴露了一个 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
})
这就是那些基于环境的 "summed" 与预定义的
Spring 不会被重复混淆,因为它只取第一个兼容的。
看看如何选择 HttpMessageConverter
你可以看到它只是一个简单的for循环,并且要求每个convert通过canWrite
方法说"can I do this?"
第一个有效的被选中。
我将 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
因为我自己没有初始化任何消息转换器:为什么应用程序上下文根本包含重复的转换器,然后将它们添加到 resttemplate 中?
特别是:如果某些转换器出现重复(但配置不同),这不会混淆(反)序列化吗?
例如:第一个 MappingJackson2HttpMessageConverter
的 ObjectMapper
比第二个(仅包含:[Jdk8Module, JavaTimeModule]
)包含更多 registeredModuleTypes
[Jdk8Module, JavaTimeModule, ParamterNamesModule, JsonComponentModule, GeoModule]
。
这有意义吗?
它是通过 RestTemplateAutoConfiguration.restTemplateBuilder()
实例化的,所有重复的 MessageConverters
都已经存在。
罪魁祸首在这里,在 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)。
基于环境。
然后该列表与 默认值 由 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
状态
This class registers ... ... a range of
HttpMessageConverters
depending on the third-party libraries available on the classpath.
扫描的 HttpMessageConverter
(s) 是通过 HttpMessageConvertersAutoConfiguration
找到并实例化的,其文档是
Auto-configuration for
HttpMessageConverters
.
那个 class 自己暴露了一个 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
})
这就是那些基于环境的 "summed" 与预定义的
Spring 不会被重复混淆,因为它只取第一个兼容的。
看看如何选择 HttpMessageConverter
你可以看到它只是一个简单的for循环,并且要求每个convert通过canWrite
方法说"can I do this?"
第一个有效的被选中。