Архитектура Java для привязки XML (JAXB) — это технология привязки XML к объектам Java, которая упрощает разработку веб-сервисов, обеспечивая преобразования между схемой XML и объектами Java, а также между документами XML и объектами Java. Схема XML определяет элементы данных и структуру документа XML. Вы можете использовать API и инструменты JAXB для установления соответствия между классами Java и схемой XML. Технология JAXB предоставляет инструменты, которые позволяют конвертировать XML-документы в объекты Java и обратно.
Используя JAXB, можно манипулировать объектами данных следующими способами.
-
Начав с определения схемы XML (XSD), использовать xjc
(инструмент компилятора схемы JAXB), чтобы создать набор JAXB-аннотированных классов Java, которые отображаются на элементы и типы, определённые в XSD-схеме.
-
Начав с набора классов Java, использовать schemagen
(инструмент генератора схем JAXB) для генерации схемы XML.
-
Как только сопоставление между схемой XML и классами Java установлено, можно использовать среду выполнения JAXB для преобразования документов XML в объекты Java и обратно и использовать полученные классы Java при компоновке приложения веб-сервисов.
XML является распространённым форматом, который RESTful сервисы принимают и в котором отдают документы. Для десериализации и сериализации XML вы можете представлять запросы и ответы аннотированными объектами JAXB. Ваше приложение JAX-RS может использовать объекты JAXB для манипулирования данными XML. Объекты JAXB могут использоваться в качестве параметров объекта запроса и объекта ответа. Среда выполнения JAX-RS включает в себя стандартные интерфейсы провайдеров MessageBodyReader
и MessageBodyWriter
для чтения и записи объектов JAXB.
С JAX-RS вы делаете доступными ваши сервисы путём публикации ресурсов. Ресурсы — это просто классы Java с некоторыми дополнительными аннотациями JAX-RS. Эти аннотации выражают следующее:
-
Путь к ресурсу (URL, который используется для доступа к нему)
-
Метод HTTP, который используется для вызова определённого метода (например, GET
или POST
)
-
Тип MIME, который метод принимает в запросе или использует в ответе
Когда вы определяете ресурсы для своего приложения, учитывайте тип данных, которые вы хотите предоставить. Возможно, у вас уже есть реляционная база данных, содержащая информацию, которую вы хотите предоставить пользователям. Или у вас может быть статический контент, который не находится в базе данных, но должен распространяться как ресурсы. Используя JAX-RS, вы можете распространять контент из нескольких источников. RESTful веб-сервисы могут использовать различные типы форматов ввода/вывода для запроса и ответа. Пример customer
, описанный в Приложение customer, использует XML.
Ресурсы имеют представления. Представление ресурса — это содержимое в HTTP-сообщении, которое отправляется или возвращается из ресурса с использованием URI. Каждое представление, поддерживаемое ресурсом, имеет соответствующий тип MIME. Например, если ресурс собирается возвращать содержимое в формате XML, можно использовать application/xml
в качестве связанного типа MIME в HTTP-сообщении. В зависимости от требований приложения ресурсы могут возвращать представления в одном формате или в нескольких. JAX-RS предоставляет аннотации @Consumes
и @Produces
для объявления типов MIME, приемлемых для метода ресурса для чтения и записи.
JAX-RS также преобразует типы Java в представления ресурсов и обратно с использованием провайдеров сущностей. Провайдер сущностей MessageBodyReader
считывает объект запроса и десериализует его в объект Java. Провайдер сущностей MessageBodyWriter
сериализует из объекта Java в объект ответа. Например, если в качестве параметра объекта запроса используется значение String
, провайдер сущностей MessageBodyReader
десериализует тело запроса в новую String
. Если тип JAXB используется в качестве возвращаемого типа для метода ресурса, MessageBodyWriter
сериализует объект JAXB в тело ответа.
По умолчанию среда выполнения JAX-RS пытается создать и использовать класс по умолчанию JAXBContext
для классов JAXB. Однако, если JAXBContext
не подходит, то вы можете предоставить класс JAXBContext
для приложения, используя интерфейс провайдера JAX-RS ContextResolver
.
В следующих разделах объясняется, как использовать JAXB с методами ресурсов JAX-RS.
Использование объектов Java для моделирования пользовательских данных
Если у вас не определена схема XML для данных, которые вы хотите представить, вы можете смоделировать свои данные как классы Java, добавить аннотации JAXB к этим классам и использовать JAXB для генерации схемы XML для ваших данных. Например, если данные, которые вы хотите предоставить, представляют собой набор продуктов, и каждый продукт имеет идентификатор, имя, описание и цену, вы можете смоделировать его как класс Java следующим образом:
@XmlRootElement(name="product")
@XmlAccessorType(XmlAccessType.FIELD)
public class Product {
@XmlElement(required=true)
protected int id;
@XmlElement(required=true)
protected String name;
@XmlElement(required=true)
protected String description;
@XmlElement(required=true)
protected int price;
public Product() {}
// get- и set- методы
// ...
}
Запустите генератор схемы JAXB в командной строке, чтобы сгенерировать соответствующую схему XML:
Эта команда создаёт схему XML в виде файла .xsd
:
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="product" type="product"/>
<xs:complexType name="product">
<xs:sequence>
<xs:element name="id" type="xs:int"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="price" type="xs:int"/>
</xs:sequence>
<xs:complexType>
</xs:schema>
Получив это сопоставление, вы можете создавать объекты Product
в своём приложении, возвращать их и использовать их в качестве параметров в методах ресурсов JAX-RS. Среда выполнения JAX-RS использует JAXB для преобразования данных XML из запроса в объект Product
и для преобразования объекта Product
в данные XML для ответа. Следующий класс ресурсов предоставляет простой пример:
@Path("/product")
public class ProductService {
@GET
@Path("/get")
@Produces("application/xml")
public Product getProduct() {
Product prod = new Product();
prod.setId(1);
prod.setName("Mattress");
prod.setDescription("Queen size mattress");
prod.setPrice(500);
return prod;
}
@POST
@Path("/create")
@Consumes("application/xml")
public Response createProduct(Product prod) {
// Обработка или сохранение продукта и формирование ответа
// ...
}
}
Некоторые IDE, такие как IDE NetBeans, будут запускать инструмент генератора схем автоматически во время процесса сборки, если добавить классы Java с аннотациями JAXB в проект. Подробный пример см. в разделе Приложение customer. Пример customer
содержит более сложные взаимосвязи между классами Java, которые моделируют данные, что приводит к более иерархическому представлению XML.
Начинаем с определения существующей схемы XML
Если у вас уже есть определение схемы XML в файле .xsd
для данных, которые вы хотите предоставить, используйте утилиту компиляции схемы JAXB. Рассмотрим простой пример файла .xsd
:
<xs:schema targetNamespace="http://xml.product"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns:myco="http://xml.product">
<xs:element name="product" type="myco:Product"/>
<xs:complexType name="Product">
<xs:sequence>
<xs:element name="id" type="xs:int"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="price" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Запустите утилиту компиляции схемы в командной строке следующим образом:
Эта команда генерирует исходный код для классов Java, которые соответствуют типам, определённым в файле .xsd
. Утилита компиляции схемы создаёт класс Java для каждого элемента complexType
из файла .xsd
. Поля каждого сгенерированного Java-класса совпадают с элементами внутри соответствующего complexType
, и класс содержит get- и set- методы для этих полей.
В этом случае утилита компиляции схемы генерирует классы product.xml.Product
и product.xml.ObjectFactory
. Класс Product
содержит аннотации JAXB, и его поля соответствуют полям в определении .xsd
:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Product", propOrder = {
"id",
"name",
"description",
"price"
})
public class Product {
protected int id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true)
protected String description;
protected int price;
// get- и set- методы
// ...
}
Вы можете создавать объекты класса Product
из своего приложения (например, из базы данных). Сгенерированный класс product.xml.ObjectFactory
содержит метод, который позволяет преобразовывать эти объекты в элементы JAXB, которые могут быть возвращены в виде XML внутри методов ресурсов JAX-RS:
@XmlElementDecl(namespace = "http://xml.product", name = "product")
public JAXBElement<Product> createProduct(Product value) {
return new JAXBElement<Product>(_Product_QNAME, Product.class, null, value);
}
В следующем коде показано, как использовать сгенерированные классы для возврата элемента JAXB в виде XML в методе ресурса JAX-RS:
@Path("/product")
public class ProductService {
@GET
@Path("/get")
@Produces("application/xml")
public JAXBElement<Product> getProduct() {
Product prod = new Product();
prod.setId(1);
prod.setName("Mattress");
prod.setDescription("Queen size mattress");
prod.setPrice(500);
return new ObjectFactory().createProduct(prod);
}
}
Для методов ресурсов @POST
и @PUT
вы можете использовать объект Product
непосредственно в качестве параметра. JAX-RS отображает данные XML из запроса в объект Product
.
@Path("/product")
public class ProductService {
@GET
// ...
@POST
@Path("/create")
@Consumes("application/xml")
public Response createProduct(Product prod) {
// Обработка или сохранение продукта и формирование ответа
// ...
}
}
Использование JSON с JAX-RS и JAXB
JAX-RS может автоматически читать и записывать XML с использованием JAXB, но он также может работать с данными JSON. JSON — это простой текстовый формат для обмена данными, пришедший из JavaScript. Для предыдущих примеров XML-представление продукта
<product>
<id>1</id>
<name>Mattress</name>
<description>Queen size mattress</description>
<price>500</price>
</product>
Эквивалентное представление JSON
{
"id":"1",
"name":"Mattress",
"description":"Queen size mattress",
"price":500
}
Вы можете добавить тип MIME application/json
или MediaType.APPLICATION_JSON
к аннотации @Produces
в методах ресурсов для получения ответов с данными JSON:
@GET
@Path("/get")
@Produces({"application/xml","application/json"})
public Product getProduct() { ... }
В этом примере ответом по умолчанию является XML, но если клиент делает запрос GET
, который включает такой заголовок, ответом будет объект JSON:
Методы ресурса также могут принимать данные JSON для аннотированных классов JAXB:
@POST
@Path("/create")
@Consumes({"application/xml","application/json"})
public Response createProduct(Product prod) { ... }
При отправке данных JSON с запросом POST
клиент должен включать следующий заголовок:
Content-Type: application/json