الربيع ، جاكسون والتخصيص (مثل CustomDeserializer)
-
01-10-2019 - |
سؤال
لا تزال غير مألوفة قليلاً مع الربيع ، لقد واجهت أ مشكلة وهذا يجعل من الضروري تنفيذ بلدي 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 إلى الكائنات من أجل تعديل سلوكه؟