복붙노트

[SPRING] 봄, 잭슨 및 맞춤 설정 (예 : 맞춤 디시리얼라이저)

SPRING

봄, 잭슨 및 맞춤 설정 (예 : 맞춤 디시리얼라이저)

스프링에 익숙하지 않은 나는 잭슨에 대한 커스텀 deserialzer를 구현해야하는 문제가 발생했습니다. 이 절차는 작은 자습서에 설명되어 있지만, 나는 Spring에 매달렸다. 나는 이해하지 못한다.

 ObjectMapper mapper = new ObjectMapper();

Spring MVC는 json이 컨트롤러 클래스의 메서드에 의해 deserialize 될 때 수행된다. 따라서 사용자 지정 디시리얼라이저로 기본 디시리얼라이저를 대체하기 위해 수행해야 할 작업을 알지 못합니다.

모든 제안을 환영합니다.

해결법

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

    1.Spring에서 Jackson을 어떻게 사용하는지 말하지 않으므로 및 @RequestBody 및 / 또는 @ResponseBody 주석을 통해 사용한다고 가정합니다.

    Spring에서 Jackson을 어떻게 사용하는지 말하지 않으므로 및 @RequestBody 및 / 또는 @ResponseBody 주석을 통해 사용한다고 가정합니다.

    가하는 일 중 하나는 MappingJacksonHttpMessageConverter를 포함하여 사전 구성된 HttpMessageConverter 빈들과 함께 제공되는 AnnotationMethodHandlerAdapter 빈을 등록하는 것입니다. MappingJacksonHttpMessageConverter는 Jackson 모델 주석 클래스와 마샬링을 처리합니다.

    이제 MappingJacksonHttpMessageConverter에는 setObjectMapper () 메소드가 있습니다.이 메소드를 사용하면 기본 ObjectMapper를 대체 할 수 있습니다. 그러나 MappingJacksonHttpMessageConverter는 에 의해 무대 뒤에서 생성되기 때문에 도달 할 수 없습니다.

    그러나 는 편리한 바로 가기입니다. 자신의 AnnotationMethodHandlerAdapter 빈을 선언하고, 자신의 MappingJacksonHttpMessageConverter 빈을 messageConverters 속성을 통해 주입하고, 사용자 정의 된 ObjectMapper를 주입하는 것만 큼 유효합니다.

    그런 다음 Spring 친화적 인 클래스가 아니기 때문에 사용자 정의 ObjectMapper를 빌드하는 방법에 대한 문제점이 있습니다. FactoryBean의 간단한 구현을 작성하는 것이 좋습니다.

    그래서 당신은 이런 식으로 끝날 것입니다 :

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
       <property name="messageConverters">
          <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
             <property name="objectMapper">
                <bean class="com.x.MyObjectMapperFactoryBean"/>
             </property>
          </bean>
       </property>
    </bean>
    
  2. ==============================

    2.Spring 3.1에서 이것을 수행하는 새로운 방법 : http://magicmonster.com/kb/prg/java/spring/webmvc/mvc_spring_config_namespace.html

    Spring 3.1에서 이것을 수행하는 새로운 방법 : http://magicmonster.com/kb/prg/java/spring/webmvc/mvc_spring_config_namespace.html

    http://blog.springsource.org/2011/02/21/spring-3-1-m1-mvc-namespace-enhancements-and-configuration/

    다음과 같이 할 수 있습니다 :

    <mvc:annotation-driven>
          <mvc:message-converters>
              <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                  <property name="objectMapper" ref="customObjectMapper"/>
              </bean>
          </mvc:message-converters>
      </mvc:annotation-driven>
    
  3. ==============================

    3.Rakesh가 참조한 솔루션은 Spring MVC 3.0에서 작동하지만 3.1에서는 MVC 인프라의 일부가 변경되었습니다. 결과적으로 응용 프로그램 컨텍스트에 AnnotationMethodHandlerAdapter Bean이 등록되어 있지 않을 수 있으며 초기화시 BeanCreationException이 발생하게됩니다.

    Rakesh가 참조한 솔루션은 Spring MVC 3.0에서 작동하지만 3.1에서는 MVC 인프라의 일부가 변경되었습니다. 결과적으로 응용 프로그램 컨텍스트에 AnnotationMethodHandlerAdapter Bean이 등록되어 있지 않을 수 있으며 초기화시 BeanCreationException이 발생하게됩니다.

    Spring MVC 3.1의 경우, mvc : annotation-driven 엘리먼트는 RequestMappingHandlerAdapter를 생성 할 것이므로 대신에 그 타입을 autowire해야한다. 등록 된 HttpMessageConverters 목록에 계속 액세스 할 수 있으며 MappingJacksonHttpMessageConverter에서 ObjectMapper 속성을 설정할 수 있습니다. 이것은 또한 init 내에서 약간의 변경이 필요합니다. 메서드를 HttpMessageConverters 참조 형식으로 변경합니다.

    업데이트 된 클래스는 다음과 같습니다.

    @Component
    public class JacksonFix {
        private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
        private CustomObjectMapper objectMapper;
    
        @PostConstruct
        public void init() {
            List<HttpMessageConverter<?>> messageConverters = requestMappingHandlerAdapter.getMessageConverters();
            for (HttpMessageConverter<?> messageConverter : messageConverters) {
                if (messageConverter instanceof MappingJacksonHttpMessageConverter) {
                    MappingJacksonHttpMessageConverter m = (MappingJacksonHttpMessageConverter) messageConverter;
                    m.setObjectMapper(objectMapper);
                }
            }
        }
    
        // this will exist due to the <mvc:annotation-driven/> bean
        @Autowired
        public void setRequestMappingHandlerAdapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
            this.requestMappingHandlerAdapter = requestMappingHandlerAdapter;
        }
    
        @Autowired
        public void setObjectMapper(CustomObjectMapper objectMapper) {
            this.objectMapper = objectMapper;
        }
    }
    

    업데이트 : Spring 3.1에서 가장 쉬운 일은 MVC 구성에 몇 가지 추가 구성을 추가하는 것입니다.

    <mvc:annotation-driven conversion-service="applicationConversionService">
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper" ref="customObjectMapper" />
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    

    그러면 기본 HttpMessageConverters (여전히 register-defaults = "true"로 인해 표시됨) 이전에 사용자 지정 ObjectMapper와 함께 MappingJacksonHttpMessageConverter의 새 인스턴스가 추가됩니다.

  4. ==============================

    4.필자의 경우 (Spring 3.2.4와 Jackson 2.3.1), 커스텀 시리얼 라이저를위한 XML 설정 :

    필자의 경우 (Spring 3.2.4와 Jackson 2.3.1), 커스텀 시리얼 라이저를위한 XML 설정 :

    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="false">
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="serializers">
                            <array>
                                <bean class="com.example.business.serializer.json.CustomObjectSerializer"/>
                            </array>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    

    설명되지 않은 방식으로 무언가에 의해 디폴트로 다시 덮어 씌어졌습니다.

    이것은 나를 위해 일했다 :

    @JsonSerialize(using = CustomObjectSerializer.class)
    public class CustomObject {
    
        private Long value;
    
        public Long getValue() {
            return value;
        }
    
        public void setValue(Long value) {
            this.value = value;
        }
    }
    
    public class CustomObjectSerializer extends JsonSerializer<CustomObject> {
    
        @Override
        public void serialize(CustomObject value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,JsonProcessingException {
            jgen.writeStartObject();
            jgen.writeNumberField("y", value.getValue());
            jgen.writeEndObject();
        }
    
        @Override
        public Class<CustomObject> handledType() {
            return CustomObject.class;
        }
    }
    

    내 솔루션에는 XML 구성 ( (...) )이 필요 없습니다.

  5. ==============================

    5.Spring MVC를 더 잘 알고 싶었지만 Jersey와 RESTeasy 같은 Jax-RS 구현에서는 공급자를 등록합니다. 어쩌면 봄은 비슷한 것을 할 것인가?

    Spring MVC를 더 잘 알고 싶었지만 Jersey와 RESTeasy 같은 Jax-RS 구현에서는 공급자를 등록합니다. 어쩌면 봄은 비슷한 것을 할 것인가?

  6. ==============================

    6.MappingJacksonHttpMessageConverter 상태에 대한 스프링 문서 :

    MappingJacksonHttpMessageConverter 상태에 대한 스프링 문서 :

    2.4.5 MappingJacksonHttpMessageConverter

    Jackson JSON Processor의 ObjectMapper를 사용하여 JSON을 읽고 쓸 수있는 HttpMessageConverter 구현입니다. JSON 매핑은 Jackson의 제공된 주석을 사용하여 필요에 따라 사용자 정의 할 수 있습니다. 추가 제어가 필요할 때 특정 유형에 대해 사용자 지정 JSON serializer / deserializers를 제공해야하는 경우 ObjectMapper 속성을 통해 사용자 정의 ObjectMapper를 주입 할 수 있습니다. 기본적으로이 변환기는 (application / json)을 지원합니다.

    ObjectMapper의 동작을 수정하기 위해 ObjectMapper에 액세스 할 수 없습니까?

  7. from https://stackoverflow.com/questions/3591291/spring-jackson-and-customization-e-g-customdeserializer by cc-by-sa and MIT license