如何在Spring RestTemplate中使用JAXB注释?

时间:2016-12-22 16:48:02

标签: java spring spring-mvc spring-boot jaxb

我尝试使用Spring的RestTemplate自动反序列化XML格式的响应。我正在使用Jackson的jackson-dataformat-xml模块,Spring Boot设置为自动配置。我想在我要反序列化的类中使用JAXB注释,但它似乎无法工作。这是我希望课程看起来像的样本:

@XmlRootElement(name="Book")
public class Book {

    @XmlElement(name="Title")
    private String title;
    @XmlElement(name="Author")
    private String author;

}

这基于以下XML示例:

<Book>
    <Title>My Book</Title>
    <Author>Me</Author>
</Book>

但是,如上所述注释类,字段始终设置为null。我做了一些实验,发现如果我使用Jackson的@JsonProperty注释子元素,反序列化就有效:

@XmlRootElement(name="Book")
public class Book {

    @JsonProperty("Title")
    private String title;
    @JsonProperty("Author")
    private String author;

}

它有效,但不知怎的,我觉得它有点尴尬。有没有办法让JAXB注释像我的第一个例子一样工作?

Jackson提供jackson-module-jaxb-annotations模块用于XML数据绑定以使用JAXB注释。但是,我不确定如何设置ObjectMapper使用RestTemplate来使用此模块。

4 个答案:

答案 0 :(得分:2)

要解决此问题,我需要向添加到Spring JaxbAnnotationModule的转换器使用的每个ObjectMapper注册一个RestTemplate的实例。该课程包含在杰克逊的jackson-module-jaxb-annotations模块中,我通过Gradle添加到我的版本中。

随着依赖项添加到我的项目中,我接下来要做的是配置我的应用程序使用的RestTemplate。 Spring自动配置的ObjectMapper正在使用MappingJackson2XmlHttpMessageConverter个实例。我必须向每个转换器中使用的每个JaxbAnnotationModule注册ObjectMapper个实例,因此第一个任务是使用以下方式查找所有MappingJackson2XmlHttpMessageConverter

//create module
JaxbAnnotationModule jaxbAnnotationModule = new JaxbAnnotationModule();

restTemplate.getMessageConverters().stream().filter(converter -> {
    return converter instanceof MappingJackson2XmlHttpMessageConverter;
})

一旦我拥有了所有相关的转换器,我就会将模块注册到他们的每个ObjectMappers

forEach(converter -> {
    ((MappingJackson2XmlHttpMessageConverter) converter)
            .getObjectMapper()
            .register(jaxbAnnotationModule);
});

答案 1 :(得分:1)

我怀疑在第二种情况下Spring只是忽略根级JAXB注释,因为默认情况下Jackson会正确解析类的名称。

要使用JAXB注释,您必须使用库jackson-xc

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-xc</artifactId>
</dependency>

这些艺术品也可能有用:

1)http://wiki.fasterxml.com/JacksonJAXBAnnotations

2)http://springinpractice.com/2011/12/06/jackson-json-jaxb2-xml-spring

3)How can we configure the internal Jackson mapper when using RestTemplate?

答案 2 :(得分:0)

如果@Psycho Punch提供的解决方案仍然无法为您解决,这是另一种选择:

  • 添加com.fasterxml.jackson.dataformat:jackson-dataformat-xml依赖项。
  • 在您的MappingJackson2XmlHttpMessageConverter上使用XmlMapper而不是ObjectMapper。例如:

    XmlMapper xmlMapper = new XmlMapper();
    xmlMapper.registerModule(new JaxbAnnotationModule());
    
    forEach(converter -> {
        ((MappingJackson2XmlHttpMessageConverter) converter).setObjectMapper(xmlMapper)
    });
    

HTH

答案 3 :(得分:0)

如果仍然有人需要处理此类问题,Springboot 提供了一个优雅的解决方案:

<块引用>

任何 com.fasterxml.jackson.databind.Module 类型的 bean 都会自动注册到自动配置的 Jackson2ObjectMapperBuilder 并应用于它创建的任何 ObjectMapper 实例。当您向应用程序添加新功能时,这提供了一种用于贡献自定义模块的全局机制。

因此在您的配置类之一中添加它应该就足够了:

@Bean
public Module jaxbModule() {
    return new JaxbAnnotationModule();
}

来源:https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-customize-the-jackson-objectmapper