سؤال

لا تزال غير مألوفة قليلاً مع الربيع ، لقد واجهت أ مشكلة وهذا يجعل من الضروري تنفيذ بلدي deserialzer مخصص لجاكسون. تم وصف الإجراء في صغيرة الدورة التعليمية, ، ومع ذلك ، أنا عالق مع الربيع. أنا لا أفهم ، أين

 ObjectMapper mapper = new ObjectMapper();

في فصل الربيع يتم تنفيذ MVC عندما يتم استحضار JSON بواسطة طريقة فئة وحدة التحكم. لذلك أنا لا أعرف ، ماذا أفعل من أجل استبدال Deserializer الافتراضي من قبل deserialiser مخصص.

أي اقتراحات أكثر ترحيبا.

هل كانت مفيدة؟

المحلول

أنت لا تقول كيف تستخدم جاكسون في الربيع ، لذلك سأفترض أنك تستخدمه من خلال <mvc:annotation-driven/> و ال @RequestBody و/أو @ResponseBody التعليقات التوضيحية.

أحد الأشياء التي <mvc:annotation-driven/> هل هو تسجيل أ AnnotationMethodHandlerAdapter الفاصوليا التي تأتي مع عدد من التكوين مسبقا HttpMessageConverter الفاصوليا ، بما في ذلك MappingJacksonHttpMessageConverter, ، والتي تتولى تنظيم من وإلى فصول نموذج جاكسون.

حاليا MappingJacksonHttpMessageConverter لديه setObjectMapper() الطريقة التي تتيح لك تجاوز الافتراضي ObjectMapper. لكن منذ MappingJacksonHttpMessageConverter يتم إنشاؤه خلف الكواليس بواسطة <mvc:annotation-driven/>, ، لا يمكنك الوصول إليها.

لكن، <mvc:annotation-driven/> هو مجرد اختصار مريح. إنه صحيح تمامًا أن تعلن عنك AnnotationMethodHandlerAdapter الفاصوليا ، حقنها الخاصة بك MappingJacksonHttpMessageConverter الفول (عبر messageConverters خاصية) ، وحقن مخصص الخاص بك ObjectMapper إلى أن.

لديك بعد ذلك مشكلة كيفية بناء العرف 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>

نصائح أخرى

طريقة جديدة للقيام بذلك في ربيع 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>

من المحتمل أن يعمل الحل الذي أشار إليه Rakesh مع SPRING MVC 3.0 ولكن مع 3.1 بعض البنية التحتية MVC تغير. نتيجة لذلك قد لا يكون لديك AnnotationMethodHandlerAdapter فول مسجل في سياق التطبيق الخاص بك وسوف ينتهي بك الأمر مع BeanCreationException في وقت التهيئة.

لربيع MVC 3.1 mvc:annotation-driven سيقوم العنصر بإنشاء ملف requestMappingHandlerAdapter بالنسبة لك ، لذلك يجب عليك تلقائيًا هذا النوع بدلاً من ذلك. سيظل يوفر الوصول إلى قائمة httpmessageConverters المسجلة ويسمح لك بتعيين خاصية ObjectMapper على MappingJacksonHttpMessageConverter. هذا يتطلب أيضًا تغييرًا طفيفًا داخل 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>

التي ستضيف مثيلًا جديدًا من MappingJacksonHttpMessageConverter مع الكائن المخصص قبل أي من httpmessageConverters الافتراضية (التي لا تزال موجودة بسبب register-defaults="true").

في حالتي (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>

كان بطريقة غير مفسرة مكتوبة مرة أخرى إلى الافتراضي بشيء.

هذا عمل بالنسبة لي:

CustomObject.java

@JsonSerialize(using = CustomObjectSerializer.class)
public class CustomObject {

    private Long value;

    public Long getValue() {
        return value;
    }

    public void setValue(Long value) {
        this.value = value;
    }
}

CustomObjectSerializer.java

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 (<mvc:message-converters>(...)</mvc:message-converters>) مطلوب في حلي.

أتمنى لو كنت أعرف Spring MVC أفضل ، ولكن مع تطبيقات Jax-RS مثل Jersey و Resteasy ، يسجل أحد مقدمي الخدمات. ربما الربيع يفعل شيئا مشابها؟

مستندات الربيع لدولة MapPingJacksonHttpMessageConverter:

2.4.5 MapPingJacksonHttpMessageConverter

تطبيق httpmessageConverter يمكنه قراءة وكتابة JSON باستخدام ObjectMapper معالج Jackson Json. يمكن تخصيص رسم خرائط JSON حسب الحاجة من خلال استخدام التعليقات التوضيحية المقدمة من Jackson. عندما تكون هناك حاجة إلى مزيد من التحكم ، يمكن حقن كائن مخصص من خلال خاصية ObjectMapper للحالات التي يجب توفيرها المسلسلات المخصصة لـ JSON/deserializers لأنواع محددة. بشكل افتراضي ، يدعم هذا المحول (التطبيق/JSON).

ألا يمكنك فقط الوصول إلى AutoWire إلى الكائنات من أجل تعديل سلوكه؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top