我想更新Spring RestTemplate所使用的jackson映射器的SerializationConfig.Feature ...属性,任何想法都知道如何获得它或在哪里可以/应该对其进行配置。
Answers:
默认RestTemplate
构造函数注册一组HttpMessageConverter
:
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(new StringHttpMessageConverter());
this.messageConverters.add(new ResourceHttpMessageConverter());
this.messageConverters.add(new SourceHttpMessageConverter());
this.messageConverters.add(new XmlAwareFormHttpMessageConverter());
if (jaxb2Present) {
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jacksonPresent) {
this.messageConverters.add(new MappingJacksonHttpMessageConverter());
}
if (romePresent) {
this.messageConverters.add(new AtomFeedHttpMessageConverter());
this.messageConverters.add(new RssChannelHttpMessageConverter());
}
该MappingJacksonHttpMessageConverter
轮流,造成ObjectMapper
直接实例。您可以找到该转换器并替换ObjectMapper
或注册一个新的转换器。这应该工作:
@Bean
public RestOperations restOperations() {
RestTemplate rest = new RestTemplate();
//this is crucial!
rest.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
return rest;
}
@Bean
public MappingJacksonHttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
converter.setObjectMapper(myObjectMapper());
return converter;
}
@Bean
public ObjectMapper myObjectMapper() {
//your custom ObjectMapper here
}
在XML中,遵循以下原则:
<bean id="restOperations" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<util:list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="customObjectMapper"/>
</bean>
</util:list>
</property>
</bean>
<bean id="customObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"/>
请注意,转换并不是真正的1:1-我必须以messageConverters
XML显式创建列表,而采用@Configuration
这种方法,我可以引用现有列表并简单地对其进行修改。但这应该可行。
RestOperations -> RestTemplate
的@Bean
定义,使这个作品
如果您不使用Spring IOC,则可以执行以下操作(Java 8):
ObjectMapper objectMapper = new ObjectMapper();
// configure your ObjectMapper here
RestTemplate restTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
messageConverter.setPrettyPrint(false);
messageConverter.setObjectMapper(objectMapper);
restTemplate.getMessageConverters().removeIf(m -> m.getClass().getName().equals(MappingJackson2HttpMessageConverter.class.getName()));
restTemplate.getMessageConverters().add(messageConverter);
RestTemplate将初始化其默认消息转换器。您应该用MappingJackson2HttpMessageConverter
自己的bean替换,后者应使用要使用的对象映射器。这为我工作:
@Bean
public RestTemplate restTemplate() {
final RestTemplate restTemplate = new RestTemplate();
//find and replace Jackson message converter with our own
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
final HttpMessageConverter<?> httpMessageConverter = restTemplate.getMessageConverters().get(i);
if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter){
restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter());
}
}
return restTemplate;
}
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(myObjectMapper());
return converter;
}
@Bean
public ObjectMapper myObjectMapper() {
// return your own object mapper
}
myObjectMapper()
但不仅要如此objectMapper()
。由于某种原因,似乎从未调用过该方法,而您获得了默认值ObjectMapper
。
restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter);
应该是restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter());
(请注意mappingJackson2HttpMessageConverter()中的括号,使其成为方法调用而不是引用)
mappingJackson2HttpMessageConverter
as作为参数添加到按原样restTemplate
使用的函数中。
要完成其他答案:如果你ObjectMapper
只是注册了杰克逊Module
定制的串行/解串器,你可能想直接在现有注册模块ObjectMapper
从RestTemplate
的默认MappingJackson2HttpMessageConverter
如下(例如无DI但同样适用,如果使用DI):
SimpleModule module = new SimpleModule();
module.addSerializer(...);
module.addDeserializer(...);
MappingJackson2HttpMessageConverter messageConverter = restTemplate.getMessageConverters().stream()
.filter(MappingJackson2HttpMessageConverter.class::isInstance)
.map(MappingJackson2HttpMessageConverter.class::cast)
.findFirst().orElseThrow( () -> new RuntimeException("MappingJackson2HttpMessageConverter not found"));
messageConverter.getObjectMapper().registerModule(module);
这样您就可以完成原始文件的配置ObjectMapper
(如Spring的那样Jackson2ObjectMapperBuilder
),而不是替换它。
使用Spring Boot,它很简单:
RestTemplate template = new RestTemplateBuilder()
.additionalMessageConverters(new MappingJackson2HttpMessageConverter(objectMapper))
.build()
(使用Spring Boot 2.2.1进行测试)
RestTemplate
将只有一个MessageConverter
:MappingJackson2HttpMessageConverter
。但我仍然喜欢
additionalMessageConverters
并不是真正的添加剂。它将完全替换,您将失去其他转换器。它在其文档字符串中说明。(它将添加到构建器的转换器列表中,它将完全替换实例的转换器)