在Spring 3.1.2中使用JAXB注释注册MappingJackson2HttpMessageConverter

9

我有一些带有JAXB注释的实体,我想使用消息转换器将它们转换为JSON。

我知道读取JAXB注释的ObjectMapper可以工作:

String correctJsonText = jacksonObjectMapper.writeValueAsString(entityWithJAXB); 

但是当我调用我的REST服务时,默认注册的MappingJacksonHttpMessageConverter(它没有配置用于读取JAXB)似乎接管了 - 当忽略@XmlTransient时会导致循环引用而导致stackoverflow...

我该如何配置Spring使用MappingJackson2HttpMessageConverter?

当前配置

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="false">
        <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="jacksonObjectMapper" />
            <property name="supportedMediaTypes">
                <list>
                    <bean class="org.springframework.http.MediaType">
                        <constructor-arg index="0" value="application" />
                        <constructor-arg index="1" value="json" />
                        <constructor-arg index="2" value="UTF-8" />
                    </bean>
                </list>
            </property>

        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

<bean id="jaxbAnnotationInspector" class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector" />

<bean id="jacksonObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
    <property name="annotationIntrospector" ref="jaxbAnnotationInspector" />
</bean>

REST服务

@RequestMapping(value="/{id}", method=RequestMethod.GET, produces = "application/json;charset=UTF-8")
public @ResponseBody EntityWithJAXB readEntityWithJAXB(@PathVariable int id, Model model) {
    return entityService.getById(id);
}

依赖项

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.0.5</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.0.5</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-jaxb-annotations</artifactId>
    <version>2.0.5</version>
</dependency>

更新/解决方案

通过调试我的上下文,我发现<mvc:annotation-driven>中的配置没有生效。

事实证明,我的带有MockMcv的单元测试总是加载默认的handleradapters,因此忽略了我的定制objectmapper。由于方便起见,我只使用junit测试来测试控制器,因为它可以很好地命中控制器,所以我没有想到这可能是一个潜在的错误原因……

我还没有找到我的测试修复方法,但当我使用curl调用服务时一切正常!

更新/最终解决方案

刚刚找到了我的测试设置的解决方案;当使用MockMvc(spring-test-mvc)时,必须显式指定自定义消息转换器:

private MockMvc mockMvc;

@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;

@Autowired
private RestController restController;

@Before
public void initMockMvc(){
    mockMvc = MockMvcBuilders.standaloneSetup(restController)
            .setMessageConverters(jacksonMessageConverter).build();
} 

@Test
public void testRestController() throws Exception{
    DefaultRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/json/42");
    this.mockMvc.perform(requestBuilder).andDo(print()).andExpect(status().isOk());
}

唯一剩下的问题是,jacksonMessageConverter目前无法直接进行自动装配,直到以下JIRA得到解决:https://jira.springsource.org/browse/SPR-9469。在那之前,我只是在我的测试环境中创建了一个jacksonMessageConverter的副本。

1个回答

3
我复制了您的配置,它在我的设备上运行得很完美。默认的消息转换器不应该生效,因为您已经明确地指定了register-defaults=false属性。这是我的@XmlTransient注释的样子:
@XmlAccessorType(XmlAccessType.FIELD)
public class EntityWithJAXB {


    @XmlTransient
    private EntityWithJAXB aChild;

谢谢,这是有价值的信息!我的@Xml注解在getter和setter上,但我不认为这会有任何影响。可能是配置中其他的东西弄错了……我会尝试将jackson配置移动到一个干净的项目中,看看是否适用于我。我找到解决方案后会发布它。 - molholm
1
我在一个干净的项目中进行了配置,就像您一样,没有问题。我怀疑问题是由于WebServiceMessageReceiverHandlerAdapter引起的,它会导致dispatch-servlet无法加载默认适配器或其他配置问题,但事实并非如此。 - molholm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接