7

我在我XmlMapper的一个 Spring Boot 项目中自动装配默认 Jackson 时遇到了一些问题。我创建了一个简单的示例项目来说明这一点。

我在这里所做的大致基于此:

http://docs.spring.io/spring-boot/docs/1.2.2.RELEASE/reference/htmlsingle/#howto-write-an-xml-rest-service

http://docs.spring.io/spring-boot/docs/1.2.2.RELEASE/reference/htmlsingle/#howto-customize-the-jackson-objectmapper

来自 pom.xml

<!-- ... -->

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.2.RELEASE</version>
</parent>

<!-- ... -->

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>
</dependencies>

<!-- ... -->

主要类:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Demo POJO,没有指定@XmlRootElement,所以它不会使用 JAXB:

@JsonInclude(Include.NON_NULL)
public class Demo {
    private String stringProperty;
    private int intProperty;
    public String getStringProperty() {
        return stringProperty;
    }
    public void setStringProperty(String stringProperty) {
        this.stringProperty = stringProperty;
    }
    public int getIntProperty() {
        return intProperty;
    }
    public void setIntProperty(int intProperty) {
        this.intProperty = intProperty;
    }
}

演示控制器:

@RestController
public class DemoController {
    @Autowired 
    private ObjectMapper objectMapper;
    // @Autowired 
    // private XmlMapper xmlMapper;

    @RequestMapping(value = "/demo", method = RequestMethod.GET)
    public Demo getDemo() {
        Demo demo = new Demo();
        demo.setStringProperty("Hello world!");
        demo.setIntProperty(42);
        return demo;
    }
}

一切正常,取决于Accept标头,将返回 JSON 或 XML。

我可以轻松地自动装配ObjectMapperSpring Boot 配置的默认值。到目前为止,一切都很好。

如果我在自动装配中发表评论,XmlMapper我会得到:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.fasterxml.jackson.dataformat.xml.XmlMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 18 more

知道这是为什么吗?我会假设它的工作方式与ObjectMapper. 澄清一下,我不想自定义映射器,我只想引用 Spring Boot 创建的默认映射器。

4

3 回答 3

22

根据@Andy Wilkinson 的回答,我进行了更多挖掘,并找到了一种方法来获得我想要的东西。Spring Boot 不会将XmlMapperBean 公开,但会公开它所使用的消息转换器,即MappingJackson2XmlHttpMessageConverter. 所以我可以自动连接那个bean并从中获取ObjectMapper(现在是一个XmlMapper)。

我的问题中的演示控制器现在看起来像这样:

    @RestController
    public class DemoController {
        @Autowired 
        private ObjectMapper objectMapper;
        @Autowired
        private MappingJackson2XmlHttpMessageConverter xmlConverter;

        @RequestMapping(value = "/demo", method = RequestMethod.GET)
        public Demo getDemo() {
            Demo demo = new Demo();
            demo.setStringProperty("Hello world!");
            demo.setIntProperty(42);
            ObjectMapper xmlMapper = xmlConverter.getObjectMapper();
            return demo;
        }
    }
于 2015-03-05T16:59:20.593 回答
13

Spring Boot 不会将XmlMapperbean 作为 bean 公开,因为它会与ObjectMapper用于 JSON 映射的 bean 冲突(Jackson'sXmlMapper是 Jackson's 的子类ObjectMapper)。

于 2015-03-02T15:00:36.010 回答
4

有两种方法:

@Bean
public XmlMapper xmlMapper(MappingJackson2XmlHttpMessageConverter converter) {
    return (XmlMapper) converter.getObjectMapper();
}

@Bean
@Primary
public ObjectMapper objectMapper(MappingJackson2XmlHttpMessageConverter converter) {
    return converter.getObjectMapper();
}

如果您想要支持 JSON 和 XML,那么您应该使用如何根据 Spring 中的配置创建多个相同类型的 bean 中描述的 BeanFactoryPostProcessor 方法自己注册这些 bean?

于 2019-10-03T09:08:25.407 回答