春季,杰克逊和定制(例如,定制器)
-
01-10-2019 - |
解决方案
您不会说您在春季如何使用杰克逊,所以我假设您正在使用它 <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
允许您做这样的事情:
<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”属性上设置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之前,使用自定义对象mapper(由于 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>
我的解决方案需要)。
我希望我更好地了解春季MVC,但是有了JAX-RS实施,例如Jersey和Resteasy,一个注册提供商。也许春天有类似的事情?
MappingJacksonHttpMessageConverter状态的春季文档:
2.4.5 MappingJacksonHttpMessageConverter
可以使用Jackson Json Processor的ObjectMapper读取和编写JSON的HTTPMessAgeConverter实现。可以通过使用杰克逊提供的注释根据需要定制JSON映射。当需要进一步的控制时,可以通过对ObjectMapper属性注入自定义的对象模型,对于需要为特定类型提供自定义JSON Serializer/Deserializers的情况。默认情况下,此转换器支持(应用程序/JSON)。
您不能只是自动访问对objectMapper即可修改其行为吗?