spring 使用 RestTemplate 时如何配置内部 Jackson 映射器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9381665/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 04:57:17  来源:igfitidea点击:

How can we configure the internal Hymanson mapper when using RestTemplate?

springHymanson

提问by Usman Ismail

I want to update the SerializationConfig.Feature... properties of the Hymanson mapper used by Spring RestTemplate, Any idea how I can get to it or where I can/should configure it.

我想更新 Spring RestTemplate 使用的 Hymanson 映射器的 SerializationConfig.Feature... 属性,不知道如何获取它或我可以/应该在哪里配置它。

回答by Tomasz Nurkiewicz

The default RestTemplateconstructor registers a set of HttpMessageConverters:

默认RestTemplate构造函数注册了一组HttpMessageConverters:

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 (HymansonPresent) {
    this.messageConverters.add(new MappingHymansonHttpMessageConverter());
}
if (romePresent) {
    this.messageConverters.add(new AtomFeedHttpMessageConverter());
    this.messageConverters.add(new RssChannelHttpMessageConverter());
}

The MappingHymansonHttpMessageConverterin turns, creates ObjectMapperinstance directly. You can either find this converter and replace ObjectMapperor register a new one before it. This should work:

MappingHymansonHttpMessageConverter轮流,造成ObjectMapper直接实例。您可以找到此转换器并ObjectMapper在它之前更换或注册一个新转换器。这应该有效:

@Bean
public RestOperations restOperations() {
    RestTemplate rest = new RestTemplate();
    //this is crucial!
    rest.getMessageConverters().add(0, mappingHymansonHttpMessageConverter());
    return rest;
}

@Bean
public MappingHymansonHttpMessageConverter mappingHymansonHttpMessageConverter() {
    MappingHymansonHttpMessageConverter converter = new MappingHymansonHttpMessageConverter();
    converter.setObjectMapper(myObjectMapper());
    return converter;
}

@Bean
public ObjectMapper myObjectMapper() {
    //your custom ObjectMapper here
}

In XML it is something along these lines:

在 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.MappingHymansonHttpMessageConverter">
                <property name="objectMapper" ref="customObjectMapper"/>
            </bean>
        </util:list>
    </property>
</bean>

<bean id="customObjectMapper" class="org.codehaus.Hymanson.map.ObjectMapper"/>

Note that the transition isn't really 1:1 - I have to explicitly create messageConverterslist in XML while with @Configurationapproach I could reference existing one and simply modify it. But this should work.

请注意,转换并不是真正的 1:1 - 我必须messageConverters在 XML 中显式创建列表,而使用@Configuration方法我可以引用现有列表并简单地修改它。但这应该有效。

回答by Matt Sidesinger

If you are not using Spring IOC, you can do something like this (Java 8):

如果您不使用 Spring IOC,您可以执行以下操作(Java 8):

ObjectMapper objectMapper = new ObjectMapper();
// configure your ObjectMapper here

RestTemplate restTemplate = new RestTemplate();    

MappingHymanson2HttpMessageConverter messageConverter = new MappingHymanson2HttpMessageConverter();
messageConverter.setPrettyPrint(false);
messageConverter.setObjectMapper(objectMapper);
restTemplate.getMessageConverters().removeIf(m -> m.getClass().getName().equals(MappingHymanson2HttpMessageConverter.class.getName()));
restTemplate.getMessageConverters().add(messageConverter);

回答by mvogiatzis

RestTemplate will initialize its default message converters. You should replace the MappingHymanson2HttpMessageConverterwith your own bean, which should use the object mapper you want to use. This worked for me:

RestTemplate 将初始化其默认消息转换器。您应该MappingHymanson2HttpMessageConverter用您自己的 bean替换,它应该使用您要使用的对象映射器。这对我有用:

@Bean
public RestTemplate restTemplate() {
    final RestTemplate restTemplate = new RestTemplate();

    //find and replace Hymanson message converter with our own
    for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
        final HttpMessageConverter<?> httpMessageConverter = restTemplate.getMessageConverters().get(i);
        if (httpMessageConverter instanceof MappingHymanson2HttpMessageConverter){
            restTemplate.getMessageConverters().set(i, mappingHymanson2HttpMessageConverter());
        }
    }

    return restTemplate;
}

@Bean
public MappingHymanson2HttpMessageConverter mappingHymanson2HttpMessageConverter() {
    MappingHymanson2HttpMessageConverter converter = new MappingHymanson2HttpMessageConverter();
    converter.setObjectMapper(myObjectMapper());
    return converter;
}

@Bean
public ObjectMapper myObjectMapper() {
    // return your own object mapper
}

回答by Olivier Gérardin

To complete the other answers: if your ObjectMapperjust registers a Hymanson Modulewith custom serializers/deserializers, you might want to register your module directly on the existing ObjectMapperfrom RestTemplate's default MappingHymanson2HttpMessageConverteras follows (example without DI but the same applies if using DI):

要完成其他答案:如果您ObjectMapper只是Module使用自定义序列化器/反序列化器注册 Hymanson ,您可能希望直接在现有ObjectMapperfromRestTemplate的默认值上注册您的模块MappingHymanson2HttpMessageConverter,如下所示(没有 DI 的示例,但如果使用 DI,则同样适用):

    SimpleModule module = new SimpleModule();
    module.addSerializer(...);
    module.addDeserializer(...);

    MappingHymanson2HttpMessageConverter messageConverter = restTemplate.getMessageConverters().stream()
                    .filter(MappingHymanson2HttpMessageConverter.class::isInstance)
                    .map(MappingHymanson2HttpMessageConverter.class::cast)
                    .findFirst().orElseThrow( () -> new RuntimeException("MappingHymanson2HttpMessageConverter not found"));
    messageConverter.getObjectMapper().registerModule(module);

This will allow you to complete the configuration of the original ObjectMapper(as done by Spring's Hymanson2ObjectMapperBuilder), instead of replacing it.

这将允许您完成原始配置ObjectMapper(由 Spring 的 完成Hymanson2ObjectMapperBuilder),而不是替换它。

回答by Wim Deblauwe

Using Spring Boot, it is as simple as:

使用 Spring Boot,它很简单:

RestTemplate template = new RestTemplateBuilder()
                            .additionalMessageConverters(new MappingHymanson2HttpMessageConverter(objectMapper))
                            .build()

(Tested with Spring Boot 2.2.1)

(使用 Spring Boot 2.2.1 测试)