Spring Framework 4.1忽略了ContentNegotiation中的自定义Object Mapper

时间:2015-03-09 23:35:38

标签: spring spring-mvc

我正在尝试升级到Spring 4.1.5。

我有一个像这样定义的自定义Object mapper

<bean id="apiObjectMapper" class="my.company.ApiObjectMapper" />

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="apiObjectMapper"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

对象映射器本身如下所示:

public class ApiObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;

public ApiObjectMapper() {
    JaxbAnnotationModule module = new JaxbAnnotationModule();

    module.setPriority(Priority.SECONDARY);
    registerModule(module);

    setSerializationInclusion(JsonInclude.Include.NON_NULL);
    configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}

}

问题出现在内容协商期间似乎

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorParameter" value="true" />
    <property name="defaultContentType" value="text/xml" />
    <property name="mediaTypes" >
        <value>
            json=application/json
            xml=text/xml
        </value>
    </property>
</bean>

升级后,只会忽略对象映射器。不考虑Jaxb注释,出现NULL。

Spring 4.0.9运行正常。 我尝试了Java配置,结果相同。 还尝试直接配置新的Jackson2ObjectMapperFactoryBean,但无法使原始行为发生。

例如:“list.xml”等端点的原始输出

<result>
<typeB>
    <itemA>...</itemA>
    <itemB>...</itemB>
</typeB>
</result>

现在输出(typeA为空/ null):

<result>
<typeA />
<typeB>
    <itemA>...</itemA>
    <itemB>...</itemB>
</typeB>
</result>

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我相信我找到了罪魁祸首并解决了这个问题。

当内容协商确定响应应该以JSON序列化时,则使用org.springframework.http.converter.json.MappingJackson2HttpMessageConverter。但是,如果响应应该以XML格式化,则使用org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter代替。如果没有提供默认对象映射器,将使用不同的消息转换器。

我必须改变的是

public class ApiObjectMapper extends XmlMapper { // XmlMapper extends ObjectMapper
    // same logic
}

<bean id="apiObjectMapper" class="my.company.ApiObjectMapper" />

<mvc:annotation-driven content-negotiation-    manager="contentNegotiationManager">
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="apiObjectMapper"/>
        </bean>
        <!-- Added this bean configuration for XML serialization -->
        <bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
            <property name="objectMapper" ref="apiObjectMapper"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

我还没有找到Spring Framework或Jackson中发生了哪些变化才能实现这一点,尽管我的钱是将Jackson XML处理分离到另一个库中(我会更新此答案)。

希望它有所帮助。

答案 1 :(得分:0)

留出更多信息以供将来参考。

基于this Spring blog post,从Spring 4.1开始,如果在类路径中找到前者,则使用Jackson XML生成XML而不是Jaxb。这是输出改变的主要原因,因为生成它的库发生了变化。

现在经过一些试验和错误,让Jackson XML生成与Jaxb相同的输出是非常有用的。相反,您可以删除对Jackson XML的所有引用(而不是Jackson本身),应该的所有内容都与之前的工作方式相同。