如何在 Spring 引导应用程序中自动装配默认 XmlMapper
How to autowire default XmlMapper in Spring Boot application
我在我的 Spring 引导项目之一中自动装配默认 Jackson XmlMapper
时遇到了一些问题。我创建了一个简单的示例项目来说明这一点。
我这里的做法大致是基于这个:
来自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>
<!-- ... -->
主要class:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
演示 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
headers,将返回 JSON 或 XML。
我可以轻松地自动连接 Spring Boot 配置的默认值 ObjectMapper
。到目前为止一切顺利。
如果我在 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.
创建的默认映射器
Spring Boot 不会将 XmlMapper
作为 bean 公开,因为它会与用于 JSON 映射的 ObjectMapper
bean 冲突(Jackson 的 XmlMapper
是杰克逊 ObjectMapper
).
的子类
根据@Andy Wilkinson 的回答,我进行了更多挖掘并找到了一种方法来获得我想要的东西。 Spring Boot 不会将 XmlMapper
作为 Bean 公开,但会公开使用它的消息转换器,即 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;
}
}
有两种方法:
@Bean
public XmlMapper xmlMapper(MappingJackson2XmlHttpMessageConverter converter) {
return (XmlMapper) converter.getObjectMapper();
}
和
@Bean
@Primary
public ObjectMapper objectMapper(MappingJackson2XmlHttpMessageConverter converter) {
return converter.getObjectMapper();
}
如果你想支持 JSON 和 XML 那么你应该使用
中描述的 BeanFactoryPostProcessor 方法自己注册这些 beans
我在我的 Spring 引导项目之一中自动装配默认 Jackson XmlMapper
时遇到了一些问题。我创建了一个简单的示例项目来说明这一点。
我这里的做法大致是基于这个:
来自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>
<!-- ... -->
主要class:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
演示 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
headers,将返回 JSON 或 XML。
我可以轻松地自动连接 Spring Boot 配置的默认值 ObjectMapper
。到目前为止一切顺利。
如果我在 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.
Spring Boot 不会将 XmlMapper
作为 bean 公开,因为它会与用于 JSON 映射的 ObjectMapper
bean 冲突(Jackson 的 XmlMapper
是杰克逊 ObjectMapper
).
根据@Andy Wilkinson 的回答,我进行了更多挖掘并找到了一种方法来获得我想要的东西。 Spring Boot 不会将 XmlMapper
作为 Bean 公开,但会公开使用它的消息转换器,即 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;
}
}
有两种方法:
@Bean
public XmlMapper xmlMapper(MappingJackson2XmlHttpMessageConverter converter) {
return (XmlMapper) converter.getObjectMapper();
}
和
@Bean
@Primary
public ObjectMapper objectMapper(MappingJackson2XmlHttpMessageConverter converter) {
return converter.getObjectMapper();
}
如果你想支持 JSON 和 XML 那么你应该使用