【问题标题】:How do I use JAXB annotations with Spring RestTemplate?如何在 Spring RestTemplate 中使用 JAXB 注释?
【发布时间】:2016-12-22 16:48:01
【问题描述】:

我正在尝试使用 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 为 XML 数据绑定提供了jackson-module-jaxb-annotations 模块以使用 JAXB 注释。但是,我不确定如何设置RestTemplate 使用的ObjectMapper 以使用此模块。

【问题讨论】:

  • 你解决了吗?我实际上也在尝试做同样的事情
  • @dalvarezmartinez1 是的。请在下面查看我的解决方案。

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


【解决方案1】:

为了解决这个问题,我需要为添加到 Spring 的 RestTemplate 的转换器使用的每个 ObjectMapper 注册一个 JaxbAnnotationModule 的实例。该类包含在 Jackson 的 jackson-module-jaxb-annotations 模块中,我通过 Gradle 添加到我的构建中。

将依赖项添加到我的项目后,我接下来要做的是配置我的应用程序使用的RestTemplateObjectMapper 实例由 Spring 自动配置的 MappingJackson2XmlHttpMessageConverters 使用。我必须将JaxbAnnotationModule 实例注册到每个转换器中使用的每个ObjectMapper,因此第一个任务是使用以下方法查找所有MappingJackson2XmlHttpMessageConverters:

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

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

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

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

【讨论】:

    【解决方案2】:

    我怀疑在第二种情况下 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?

    【讨论】:

    • 我错过了在我的问题中添加一些关于此的细节。但是,jackson-xc 现在实际上已经过时了,当前为 Jackson 的 XML 数据绑定添加 JAXB 支持的模块是 jackson-module-jaxb-annotations。我的问题是我不确定如何设置 RestTemplate 使用的 ObjectMapper 以使用此模块。
    • 我尝试通过ObjectMapperregisterModule() 方法注册模块,但我仍然在对象的字段中获得null 值。
    【解决方案3】:

    如果@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

    【讨论】:

      【解决方案4】:

      如果有人仍然需要处理这类问题,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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-08
        • 2018-02-23
        • 1970-01-01
        • 2016-05-01
        • 2012-02-25
        • 1970-01-01
        • 2015-03-17
        • 2011-06-20
        相关资源
        最近更新 更多