복붙노트

[SPRING] RestTemplate을 사용할 때 어떻게 내부 잭슨 매퍼를 구성 할 수 있습니까?

SPRING

RestTemplate을 사용할 때 어떻게 내부 잭슨 매퍼를 구성 할 수 있습니까?

Spring RestTemplate에서 사용하는 Jackson 매퍼의 SerializationConfig.Feature ... 속성을 업데이트하고 싶습니다. 어떤 생각이 들거나 어떻게 할 수 있는지 / 구성 할 수 있어야합니다.

해결법

  1. ==============================

    1.기본 RestTemplate 생성자는 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 (jacksonPresent) {
        this.messageConverters.add(new MappingJacksonHttpMessageConverter());
    }
    if (romePresent) {
        this.messageConverters.add(new AtomFeedHttpMessageConverter());
        this.messageConverters.add(new RssChannelHttpMessageConverter());
    }
    

    MappingJacksonHttpMessageConverter가 차례로 ObjectMapper 인스턴스를 직접 생성합니다. 이 변환기를 찾고 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이 아닙니다. XML에서 messageConverters 목록을 명시 적으로 작성해야하지만 @Configuration 방식을 사용하면 기존의 것을 참조하고 간단히 수정할 수 있습니다. 그러나 이것은 효과가있다.

  2. ==============================

    2.Spring IOC를 사용하지 않는다면 다음과 같이 할 수있다 (Java 8).

    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);
    
  3. ==============================

    3.RestTemplate은 기본 메시지 변환기를 초기화합니다. MappingJackson2HttpMessageConverter를 자신의 bean으로 대체해야하는데,이 bean은 사용할 객체 매퍼를 사용해야한다. 이것은 나를 위해 일했다 :

    RestTemplate은 기본 메시지 변환기를 초기화합니다. MappingJackson2HttpMessageConverter를 자신의 bean으로 대체해야하는데,이 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
    }
    
  4. ==============================

    4.다른 답변을 완성하려면 : ObjectMapper가 사용자 정의 serializer / deserializers로 Jackson 모듈을 등록하는 경우 RestTemplate의 기본 MappingJackson2HttpMessageConverter에서 기존 ObjectMapper에 직접 모듈을 등록 할 수 있습니다 (DI가없는 예이지만 DI를 사용하는 경우에도 동일) :

    다른 답변을 완성하려면 : ObjectMapper가 사용자 정의 serializer / deserializers로 Jackson 모듈을 등록하는 경우 RestTemplate의 기본 MappingJackson2HttpMessageConverter에서 기존 ObjectMapper에 직접 모듈을 등록 할 수 있습니다 (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에서와 같이)를 교체하는 대신 구성을 완료 할 수 있습니다.

  5. from https://stackoverflow.com/questions/9381665/how-can-we-configure-the-internal-jackson-mapper-when-using-resttemplate by cc-by-sa and MIT license