Java Platform, Enterprise Edition (Java EE) 8
Учебник по Java EE

Назад Вперёд Содержание

Использование JAX-RS с JAXB

Архитектура 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:

schemagen Product.java

Эта команда создаёт схему 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>

Запустите утилиту компиляции схемы в командной строке следующим образом:

xjc Product.xsd

Эта команда генерирует исходный код для классов 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:

Accept: application/json

Методы ресурса также могут принимать данные JSON для аннотированных классов JAXB:

@POST
@Path("/create")
@Consumes({"application/xml","application/json"})
public Response createProduct(Product prod) { ... }

При отправке данных JSON с запросом POST клиент должен включать следующий заголовок:

Content-Type: application/json

Назад Вперёд Содержание
Логотип Oracle  Copyright © 2017, Oracle и/или её дочерних компаний. Все права защищены. Версия перевода 1.0.5 (Java EE Tutorial — русскоязычная версия)