Использование SpringMVC + Spring Boot для XML
Не JSON-ом единым оперируют back-end-ы приложения. В дикой природе встречаются Web-сервисы, которые на работают с XML (да, мы не о SOAP, а именно об XML).
SpringMVC прекрасно поддерживает данную возможность, причём разными способами.
JSON c Jackson
По умолчанию spring-boot-starter-web содержит настроенный Jackson для маппинга request/response DTO в JSON.
Раз:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
(включает в себя jackson-databind)
Два:
@RequiredArgsConstructor @Getter public class PersonJsonDto { @JsonProperty("firstName") private final String name; private final int age; }
Три:
@RestController public class PersonJsonController { @GetMapping("/api/json") public PersonJsonDto json() { return new PersonJsonDto("Ivan", 18); } }
Данный контроллер содержит аннотацию @RestController, которая содержит @ResponseBody, которая в свою очередь говорит Spring MVC преобразовывать объект, используя существующие мапперы. Да, по умолчанию подразумевается application/json, для которого уже есть настроенный Jackson.
Проверяем:
GET http://localhost:8080/api/json HTTP/1.1 200 Content-Type: application/json ... { "age": 18, "firstName": "Ivan" }
XML c Jackson
Jackson, на самом деле, не “библиотека для маппинга в JSON”, а полноценный фреймворк для маппинга объектов не только в JSON, но и в XML, YAML и даже в бинарных форматах.
Подобные расширения Jacson называются dataformat.
Подключим соответствующую JAR:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
В лучших традициях Spring Boot эта библиотека сразу будет настроена spring-boot-starter-mvc.
Напишем соответствующий DTO:
@JacksonXmlRootElement( namespace = "http://otus.ru/spring", localName = "person" ) @RequiredArgsConstructor @Getter public class PersonXmlDto { private final String name; private final int age; }
Да, стоит отметить, что c маппингом XML не всё так просто. Теперь поля объекта могут быть как вложенными тегами, так и атрибутами. И не стоит забывать про namespaces элементов. Пример, представленный здесь, не лишён недостатков, поэтому искушённым читателям предлагается прочитать документацию.
И напишем контроллер:
@RestController public class PersonXmlController { @GetMapping( value = "/api/jackson-xml", produces = "application/xml" ) public PersonXmlDto jacksonXml() { return new PersonXmlDto("Ivan", 18); } }
Обратите внимание на параметр аннотации produces — здесь мы задали application/xml, чтобы сработал именно XML-маппер.
Если мы ничего не напишем, то значение по умолчанию — application/json и будет действовать именно Jackson JSON dataformat, как в предыдущем примере.
Кстати, если мы будем принимать XML на вход с помощью @RequestBody, то нам необходимо будет указать уже consumes.
Проверяем:
GET http://localhost:8080/api/jackson-xml HTTP/1.1 200 Content-Type: application/xml ... <person xmlns="http://otus.ru/spring"> <name xmlns="">Ivan</name> <age xmlns="">18</age> </person>
JAXB и Spring MVC
Говоря об XML в Java, часто подразумевают именно JAXB. JAXB исключена из стандартной поставки Java 11, поэтому добавим вместо jackson-dataformat-xml зависимость:
<dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> </dependency>
DTO выглядит похожим образом:
@XmlRootElement( namespace = "http://spring.otus.ru", name = "person-jaxb" ) @NoArgsConstructor @AllArgsConstructor @Getter @Setter public class PersonJaxbDto { private String name; private int age; }
И, как мы уже знаем, необходимо написать соответствующим образом контроллер:
@RestController public class PersonJaxbController { @GetMapping( value = "/api/jaxb-xml", produces = "application/xml" ) public PersonJaxbDto jacksonXml() { return new PersonJaxbDto("Ivan", 18); } }
И, наконец, пробуем!
GET http://localhost:8080/api/jaxb-xml Content-Type: application/xml ... <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ns2:person-jaxb xmlns:ns2="http://spring.otus.ru"> <age>18</age> <name>Ivan</name> </ns2:person-jaxb>
Весь код доступен по ссылке. Успехов!