Как автоматически подключить XmlMapper по умолчанию в приложении Spring Boot
У меня возникли некоторые проблемы с автоматической проводкой по умолчанию Джексон XmlMapper
в одном из моих проектов Spring Boot. Я создал простой пример проекта, который иллюстрирует это.
То, что я делаю здесь, примерно основано на этом:
http://docs.spring.io/spring-boot/docs/1.2.2.RELEASE/reference/htmlsingle/
http://docs.spring.io/spring-boot/docs/1.2.2.RELEASE/reference/htmlsingle/
Из 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);
}
}
Демо 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 будут возвращены.
Я могу легко подключить по умолчанию ObjectMapper
настроен Spring 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.
2 ответа
Spring Boot не выставляет XmlMapper
как боб, поскольку это будет конфликтовать с ObjectMapper
бин, который используется для отображения JSON (Джексона XmlMapper
это подкласс Джексона ObjectMapper
).
Основываясь на ответе @ Энди Уилкинсона, я еще немного покопался и нашел способ получить то, что хотел. Spring Boot не выставляет XmlMapper
как бин, но он предоставляет конвертер сообщений, в котором он используется, MappingJackson2XmlHttpMessageConverter
, Так что я могу автоматически подключить этот боб и получить 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, вам следует зарегистрировать эти bean-компоненты самостоятельно с помощью метода BeanFactoryPostProcessor, описанного в разделе Как создать несколько bean-компонентов одного типа в соответствии с конфигурацией в Spring?