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

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

Создание класса корневого ресурса RESTful

Корневые классы ресурсов — это POJO, которые либо аннотированы @Path, либо имеют хотя бы один метод, аннотированный @Path, или указатель метода запроса, такие как @GET, @PUT, @POST или @DELETE. Методы ресурса — это методы класса ресурса, аннотированные указателем метода запроса. В этом разделе объясняется, как использовать JAX-RS для аннотирования классов Java для создания RESTful веб-сервисов.

Здесь рассматриваются следующие темы:

Разработка RESTful веб-сервисов с JAX-RS

JAX-RS — это API Java, разработанный для упрощения разработки приложений, использующих архитектуру REST.

API JAX-RS использует аннотации Java для упрощения разработки RESTful веб-сервисов. Разработчики декорируют файлы классов Java аннотациями JAX-RS, чтобы задать ресурсы и действия, которые могут быть выполнены с этими ресурсами. Аннотации JAX-RS являются аннотациями времени выполнения. Следовательно, reflection во время выполнения сгенерирует вспомогательные классы и артефакты для ресурса. В архиве приложения Java EE, содержащем классы ресурсов JAX-RS, будут настроены ресурсы, сгенерированы вспомогательные классы и артефакты, а также ресурс, предоставленный клиентам путём развёртывания архива на сервере Java EE.

Таблица 30-1 перечисляет некоторые аннотации Java, определённые в JAX-RS, с кратким описанием их использования. Дополнительную информацию об API JAX-RS можно посмотреть по ссылке http://docs.oracle.com/javaee/7/api/.

Таблица 30-1. Обзор аннотаций JAX-RS

Аннотация

Описание

@Path

Значение аннотации @Path представляет собой относительный путь URI, указывающий, где будет размещён класс Java: например, /helloworld. Вы также можете встраивать переменные в URI для создания шаблона пути URI. Например, вы можете запросить имя пользователя и передать его приложению в качестве переменной в URI: /helloworld/{username}.

@GET

Аннотация @GET является указателем метода запроса и соответствует одноимённому HTTP-методу. Аннотированный таким образом метод Java будет обрабатывать HTTP GET-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

@POST

Аннотация @POST является указателем метода запроса и соответствует одноимённому HTTP-методу. Аннотированный таким образом метод Java будет обрабатывать HTTP POST-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

@PUT

Аннотация @PUT является указателем метода запроса и соответствует одноимённому HTTP-методу. Аннотированный таким образом метод Java будет обрабатывать HTTP PUT-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

@DELETE

Аннотация @DELETE является указателем метода запроса и соответствует одноимённому HTTP-методу. Аннотированный таким образом метод Java будет обрабатывать HTTP DELETE-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

@HEAD

Аннотация @HEAD является указателем метода запроса и соответствует одноимённому HTTP-методу. Аннотированный таким образом метод Java будет обрабатывать HTTP HEAD-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

@OPTIONS

Аннотация @OPTIONS является указателем метода запроса и соответствует одноимённому HTTP-методу. Аннотированный таким образом метод Java будет обрабатывать HTTP OPTIONS-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

@PATCH

Аннотация @PATCH является указателем метода запроса и соответствует одноимённому HTTP-методу. Аннотированный таким образом метод Java будет обрабатывать HTTP PATCH-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

@PathParam

Аннотация @PathParam — это тип параметра, который может быть извлечён для использования в классе ресурсов. Параметры пути URI извлекаются из URI запроса, а имена параметров соответствуют именам переменных шаблона пути URI, указанным в аннотации на уровне класса @Path.

@QueryParam

Аннотация @QueryParam — это тип параметра, который может быть извлечён для использования в классе ресурсов. Параметры запроса извлекаются из URI запроса.

@Consumes

Аннотация @Consumes используется для указания типов MIME, которые может принимать ресурс и которые были отправлены клиентом.

@Produces

Аннотация @Produces используется для указания типов MIME, которые ресурс может создавать и отправлять обратно клиенту: например, «text/plain».

@Provider

Аннотация @Provider используется для всего, что представляет интерес для среды выполнения JAX-RS, например MessageBodyReader и MessageBodyWriter. Для HTTP-запросов MessageBodyReader используется для сопоставления тела объекта HTTP-запроса с параметрами метода. Возвращаемое значение сопоставляется с телом объекта HTTP-ответа с помощью MessageBodyWriter. Если приложению необходимо предоставить дополнительные метаданные, такие как заголовки HTTP или другой код состояния, метод может вернуть Response-обёртку (wrapper) сущности и который может быть создан с использованием Response.ResponseBuilder.

@ApplicationPath

Аннотация @ApplicationPath используется для назначения URL приложению. Путь, указанный в @ApplicationPath, является базовым URI для всех URI ресурсов, указанных в аннотациях @Path в классе ресурсов. Аннотация @ApplicationPath может быть применена только к дочернему классу javax.ws.rs.core.Application.

Обзор приложения JAX-RS

Следующий пример кода — очень простой пример корневого класса ресурсов, который использует аннотации JAX-RS:

package javaeetutorial.hello;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

/**
 * Корневой ресурс (соответствует пути "helloworld")
 */
@Path("helloworld")
public class HelloWorld {
    @Context
    private UriInfo context;

    /** Инстанцирование */
    public HelloWorld() {
    }

    /**
     * Получение представления объекта helloWorld.HelloWorld
     * @return объект типа java.lang.String
     */
    @GET
    @Produces("text/html")
    public String getHtml() {
        return "<html lang=\"en\"><body><h1>Hello, World!!</h1></body></html>";
    }
}

В следующих разделах описаны аннотации, используемые в этом примере.

  • Значение аннотации @Path представляет собой относительный путь URI. В предыдущем примере класс Java будет размещён по пути URI /helloworld. Это чрезвычайно простое использование аннотации @Path со статическим путём URI. Переменные могут быть встроены в URI. Шаблоны пути URI — это URI с переменными, встроенными в синтаксис URI.

  • Аннотация @GET является указателем метода запроса, наряду с @POST, @PUT, @DELETE и @HEAD, определёнными JAX-RS и соответствующими одноимённым HTTP-методам. В этом примере аннотированный Java-метод будет обрабатывать HTTP GET-запросы. Поведение ресурса определяется HTTP-методом, на который отвечает ресурс.

  • Аннотация @Produces используется для указания типов MIME, которые ресурс может создавать и отправлять обратно клиенту. В этом примере метод Java создаёт представления с типом MIME "text/html".

  • Аннотация @Consumes используется для указания типов MIME, которые может принимать ресурс и которые были отправлены клиентом. Пример можно изменить, чтобы установить сообщение, возвращаемое методом getHtml, как показано в следующем примере кода:

    @POST
    @Consumes("text/plain")
    public void postHtml(String message) {
        // Сохранение сообщения
    }

Аннотация @Path и шаблоны пути URI

Аннотация @Path идентифицирует шаблон пути URI, на который отвечает ресурс, и указывается на уровне класса или метода ресурса. Значение аннотации @Path является частичным шаблоном пути URI относительно базового URI сервера, на котором развёрнут ресурс, корневого контекста приложения и шаблона URL, по которому отвечает среда JAX-RS времени выполнения.

Шаблоны пути URI — это URI с переменными, встроенными в синтаксис URI. Эти переменные подставляются во время выполнения, чтобы ресурс отвечал на запрос на основе замещённого URI. Переменные обозначаются фигурными скобками ({ и }). Например, посмотрите на следующую аннотацию @Path:

@Path("/users/{username}")

В этом примере пользователю предлагается ввести имя, а затем отвечает веб-сервис JAX-RS, настроенный для ответа на запросы к этому шаблону пути URI. Например, если пользователь вводит имя пользователя «Galileo», веб-сервис отвечает на следующий URL:

http://example.com/users/Galileo

Чтобы получить значение имени пользователя, можно использовать аннотацию @PathParam для параметра метода запроса, как показано в следующем примере кода:

@Path("/users/{username}")
public class UserResource {

    @GET
    @Produces("text/xml")
    public String getUser(@PathParam("username") String userName) {
        ...
    }
}

По умолчанию переменная URI должна соответствовать регулярному выражению "[^/]+?". Эту переменную можно настроить, указав другое регулярное выражение после имени переменной. Например, если имя пользователя должно состоять только из строчных и прописных буквенно-цифровых символов, переопределите регулярное выражение по умолчанию в определении переменной:

@Path("users/{username: [a-zA-Z][a-zA-Z_0-9]*}")

В этом примере переменная username будет соответствовать только именам пользователей, которые начинаются с одной заглавной или строчной буквы, а также с нуля или более буквенно-цифровых символов и символа подчеркивания. Если имя пользователя не соответствует этому шаблону, клиенту будет отправлен ответ 404 (Not Found).

Значение @Path не обязательно должно иметь начальную или конечную косую черту (/). Среда выполнения JAX-RS анализирует шаблоны пути URI одинаково, независимо от того, имеют ли они начальную или конечную косую черту.

Шаблон пути URI имеет одну или несколько переменных, каждое имя переменной заключено в фигурные скобки: { для начала имени переменной и } для её завершения. В предыдущем примере username является именем переменной. Во время выполнения ресурс, настроенный для ответа на предыдущий шаблон пути URI, попытается обработать данные URI, которые соответствуют расположению {username} в URI, в качестве переменных данных для username.

Например, если вы хотите развернуть ресурс, отвечающий шаблону пути URI http://example.com/myContextRoot/resources/{name1}/{name2}/ сначала необходимо развернуть приложение на сервере Java EE, отвечающее на запросы к URI http://example.com/myContextRoot, а затем аннотировать ресурс аннотацией @Path:

@Path("/{name1}/{name2}/")
public class SomeResource {
    ...
}

В этом примере по умолчанию используется шаблон URL для вспомогательного сервлета JAX-RS, указанный в web.xml:

<servlet-mapping>
      <servlet-name>javax.ws.rs.core.Application</servlet-name>
      <url-pattern>/resources/*</url-pattern>
</servlet-mapping>

Имя переменной может использоваться более одного раза в шаблоне пути URI.

Если символ в значении переменной будет конфликтовать с зарезервированными символами URI, конфликтующий символ должен быть URL-кодирован. Например, пробелы в значении переменной должны быть заменены на %20.

При определении шаблонов пути URI, будьте осторожны, чтобы результирующий URI после замены был валидным.

Таблица 32-2 перечисляет некоторые примеры переменных шаблона пути URI и того, как URI разрешаются после замены. В примерах используются следующие имена и значения переменных:

  • name1: james

  • name2: gatz

  • name3:

  • location: Main%20Street

  • question: why

Замечание:

Значение переменной name3 — пустая строка.

Таблица 32-2 Примеры шаблонов пути URI

Шаблон пути URI

URI после замены

http://example.com/{name1}/{name2}/

http://example.com/james/gatz/

http://example.com/{question}/{question}/{question}/

http://example.com/why/why/why/

http://example.com/maps/{location}

http://example.com/maps/Main%20Street

http://example.com/{name3}/home/

http://example.com//home/

Ответ на HTTP-методы и запросы

Поведение ресурса определяется методами HTTP (обычно GET, POST, PUT или DELETE), на которые отвечает ресурс.

Здесь рассматриваются следующие темы:

Обозначение указателя метода запроса

Аннотации указателя метода запроса — это аннотации времени выполнения, определённые JAX-RS, которые соответствуют одноимённым HTTP-методам. В файле класса ресурсов методы HTTP отображаются на методы Java с помощью аннотаций указателя метода запроса. Поведение ресурса определяется тем, на какой метод HTTP он отвечает. JAX-RS определяет набор указателей методов запроса для общих методов HTTP GET, POST, PUT, DELETE и HEAD. Вы также можете создавать свои собственные обозначения метода запроса. Создание кастомных указателей методов запроса выходит за рамки этого документа.

В следующем примере показано использование метода PUT для создания или обновления контейнера хранения:

@PUT
public Response putContainer() {
    System.out.println("PUT CONTAINER " + container);

    URI uri =  uriInfo.getAbsolutePath();
    Container c = new Container(container, uri.toString());

    Response r;
    if (!MemoryStore.MS.hasContainer(c)) {
        r = Response.created(uri).build();
    } else {
        r = Response.noContent().build();
    }

    MemoryStore.MS.createContainer(c);
    return r;
}

По умолчанию среда выполнения JAX-RS автоматически поддерживает методы HEAD и OPTIONS, если они явно не реализованы. Для HEAD среда выполнения вызовет реализованный метод GET, если он присутствует, и проигнорирует объект ответа, если он установлен. Для OPTIONS заголовок ответа Allow будет установлен на набор HTTP-методов, поддерживаемых ресурсом. Кроме того, среда выполнения JAX-RS возвратит документ WADL, описывающий ресурс. См. http://www.w3.org/Submission/wadl/ для получения дополнительной информации.

Методы, аннотированные указателями методов запроса, должны возвращать void, тип Java или объект javax.ws.rs.core.Response. Несколько параметров могут быть извлечены из URI аннотациями @PathParam и @QueryParam, как описано в Извлечение параметров запроса. За преобразование между типами Java и телом объекта отвечает провайдер сущностей, такой как MessageBodyReader или MessageBodyWriter. Методы, которым необходимо предоставить дополнительные метаданные с ответом, должны возвращать объект класса Response. Класс ResponseBuilder предоставляет удобный способ создания объекта Response с использованием конструктора (builder). Методы HTTP PUT и POST ожидают тело HTTP-запроса, поэтому вы должны использовать MessageBodyReader для методов, которые отвечают на запросы PUT и POST.

И @PUT, и @POST можно использовать для создания или обновления ресурса. POST может означать что угодно, поэтому при использовании POST семантика определяется приложением. PUT имеет чётко определённую семантику. При использовании PUT для создания клиент объявляет URI для вновь созданного ресурса.

PUT имеет очень чёткую семантику для создания и обновления ресурса. Представление, отправляемое клиентом, должно быть тем же представлением, которое получено с использованием GET, с тем же типом MIME. PUT не позволяет частично обновлять ресурс, что является распространённой ошибкой при попытке использовать метод PUT. Распространённым шаблоном приложения является использование POST для создания ресурса и возврата ответа 201 с заголовком местоположения, значением которого является URI для вновь созданного ресурса. В этом шаблоне веб-сервис объявляет URI для вновь созданного ресурса.

Использование провайдеров сущностей для сопоставления HTTP-ответа и запроса тел сущностей

Поставщики сущностей предоставляют сервисы отображения между представлениями и связанными с ними типами Java. Есть два типа провайдеров сущностей: MessageBodyReader и MessageBodyWriter. Для HTTP-запросов MessageBodyReader используется для сопоставления тела объекта HTTP-запроса с параметрами метода. Возвращаемое значение сопоставляется с телом объекта HTTP-ответа с помощью MessageBodyWriter. Если приложению необходимо предоставить дополнительные метаданные, такие как заголовки HTTP или другой код состояния, метод может вернуть Response, оборачивающий сущность и который может быть построен с помощью Response.ResponseBuilder.

Таблица 32-3 показывает стандартные типы, которые автоматически поддерживаются для тел объектов HTTP-запросов и ответов. Если не выбирается один из следующих стандартных типов, то требуется написать провайдер сущностей.

Таблица 32-3. Типы, поддерживаемые для объектов запросов и ответов HTTP

Тип Java Поддерживаемые типы медиа

byte[]

Все типы MIME (/)

java.lang.String

Все текстовые типы MIME (text/*)

java.io.InputStream

Все типы MIME (/)

java.io.Reader

Все типы MIME (/)

java.io.File

Все типы MIME (/)

javax.activation.DataSource

Все типы MIME (/)

javax.xml.transform.Source

XML типы MIME (text/xml, application/xml и application/*+xml)

javax.xml.bind.JAXBElement и предоставляемые приложением классы JAXB

XML типы MIME (text/xml, application/xml и application/*+xml)

MultivaluedMap<String, String>

Содержимое формы (application/x-www-form-urlencoded)

StreamingOutput

Все типы MIME (/), только MessageBodyWriter

В следующем примере показано, как использовать MessageBodyReader с аннотациями @Consumes и @Provider:

@Consumes("application/x-www-form-urlencoded")
@Provider
public class FormReader implements MessageBodyReader<NameValuePair> {

В следующем примере показано, как использовать MessageBodyWriter с аннотациями @Produces и @Provider:

@Produces("text/html")
@Provider
public class FormWriter implements
        MessageBodyWriter<Hashtable<String, String>> {

В следующем примере показано, как использовать ResponseBuilder:

@GET
public Response getItem() {
    System.out.println("GET ITEM " + container + " " + item);

    Item i = MemoryStore.MS.getItem(container, item);
    if (i == null)
        throw new NotFoundException("Item not found");
    Date lastModified = i.getLastModified().getTime();
    EntityTag et = new EntityTag(i.getDigest());
    ResponseBuilder rb = request.evaluatePreconditions(lastModified, et);
    if (rb != null)
        return rb.build();

    byte[] b = MemoryStore.MS.getItemData(container, item);
    return Response.ok(b, i.getMimeType()).
            lastModified(lastModified).tag(et).build();
}

Использование @Consumes и @Produces для настройки запросов и ответов

Информация, отправляемая ресурсу и затем возвращаемая клиенту, указывается как тип MIME в заголовках HTTP-запроса или ответа. Вы можете указать типы MIME, на которые ресурс может реагировать или которые может создавать, используя следующие аннотации:

  • javax.ws.rs.Consumes

  • javax.ws.rs.Produces

По умолчанию класс ресурсов может отвечать и генерировать все типы MIME, указанные в заголовках HTTP-запроса и ответа.

Здесь рассматриваются следующие темы:

Аннотация @Produces

Аннотация @Produces используется для указания типов MIME, которые ресурс может создавать и отправлять обратно клиенту. Если @Produces применяется на уровне класса, все методы в ресурсе могут создавать указанные типы MIME по умолчанию. При использовании на уровне метода аннотации переопределяют любые аннотации @Produces уровня класса.

Если никакие методы в ресурсе не могут создать содержимое указанного в запросе клиента типа MIME, среда выполнения JAX-RS отправляет обратно ошибку HTTP «406 Not Acceptable».

Значением @Produces является массив String типов MIME или разделённый запятыми список констант MediaType. Например:

@Produces({"image/jpeg,image/png"})

В следующем примере показано, как применить @Produces как на уровне класса, так и на уровне метода:

@Path("/myResource")
@Produces("text/plain")
public class SomeResource {
    @GET
    public String doGetAsPlainText() {
        ...
    }

    @GET
    @Produces("text/html")
    public String doGetAsHtml() {
        ...
    }
}

Метод doGetAsPlainText по умолчанию использует тип MIME аннотации @Produces на уровне класса. Аннотация @Produces метода doGetAsHtml переопределяет параметр @Produces уровня класса и указывает, что метод может создавать HTML, а не простой текст.

@Produces также может использовать константы, определённые в классе javax.ws.rs.core.MediaType, чтобы указать тип MIME. Например, указание MediaType.APPLICATION_XML эквивалентно указанию «application/xml».

@Produces(MediaType.APPLICATION_XML)
@GET
public Customer getCustomer() { ... }

Если класс ресурсов способен создавать более одного типа MIME, выбранный метод ресурса будет соответствовать наиболее подходящему типу MIME из числа объявленных клиентом. Более конкретно, заголовок Accept HTTP-запроса объявляет, что является наиболее приемлемым. Например, если заголовок Accept имеет значение Accept: text/plain, будет вызван метод doGetAsPlainText. В качестве альтернативы, если заголовок Accept равен Accept: text/plain;q=0.9, text/html, который объявляет, что клиент может принимать типы MIME text/plain и text/html, но предпочитающие последнее, будет вызван метод doGetAsHtml.

В одном объявлении @Produces может быть объявлено несколько типов MIME. В следующем примере кода показано, как это сделать:

@Produces({"application/xml", "application/json"})
public String doGetAsXmlOrJson() {
    ...
}

Метод doGetAsXmlOrJson будет вызван, если допустим любой из типов MIME — application/xml или application/json. Если оба одинаково приемлемы, будет выбран тот, который указан первым. Предыдущие примеры явно указывают на типы MIME для ясности. Можно ссылаться на константы, которые исключают возможность опечатки. Для получения дополнительной информации см. документацию API для значений константных полей javax.ws.rs.core.MediaType.

Аннотация @Consumes

Аннотация @Consumes используется для указания того, какие типы MIME ресурс может принимать от клиента. Если @Consumes применяется на уровне класса, все методы ответа по умолчанию принимают указанные типы MIME. При использовании на уровне метода @Consumes переопределяет любые аннотации @Consumes уровня класса.

Если ресурс не может использовать тип MIME из запроса клиента, среда выполнения JAX-RS отправляет обратно ошибку HTTP 415 («Unsupported Media Type»).

Значением @Consumes является массив String допустимых типов MIME или разделённый запятыми список констант MediaType. Например:

@Consumes({"text/plain,text/html"})

Что эквивалентно:

@Consumes({MediaType.TEXT_PLAIN,MediaType.TEXT_HTML})

В следующем примере показано, как применить @Consumes как на уровне класса, так и на уровне метода:

@Path("/myResource")
@Consumes("multipart/related")
public class SomeResource {
    @POST
    public String doPost(MimeMultipart mimeMultipartData) {
        ...
    }

    @POST
    @Consumes("application/x-www-form-urlencoded")
    public String doPost2(FormURLEncodedProperties formData) {
        ...
    }
}

Метод doPost по умолчанию использует тип MIME аннотации @Consumes на уровне класса. Метод doPost2 переопределяет аннотацию @Consumes уровня класса, указывая, что он может принимать данные формы в кодировке URL.

Если никакие методы ресурсов не могут ответить на запрошенный тип MIME, клиенту возвращается ошибка HTTP 415 («Unsupported Media Type»).

Пример HelloWorld, рассмотренный ранее в этом разделе, можно изменить, чтобы установить сообщение с помощью @Consumes, как показано в следующем примере кода:

@POST
@Consumes("text/html")
public void postHtml(String message) {
    // Сохранение сообщения
}

В этом примере метод Java будет использовать представления, идентифицированные типом MIME text/plain. Обратите внимание, что метод ресурса возвращает void. Это означает, что представление не возвращается и что будет возвращён ответ с кодом состояния HTTP 204 («No Content»).

Извлечение параметров запроса

Параметры метода ресурса могут быть аннотированы аннотациями для извлечения информации из запроса. В предыдущем примере было представлено использование параметра @PathParam для извлечения параметра пути из компонента пути URL запроса, который соответствует пути, объявленному в @Path.

Могут быть извлечены следующие типы параметров для использования в классе ресурсов:

  • Запрос

  • Путь URI

  • Форма

  • Cookie

  • Заголовок

  • Матрица

Параметры запроса извлекаются из URI запроса и задаются с помощью аннотации javax.ws.rs.QueryParam в аргументах параметра метода. В следующем примере демонстрируется использование @QueryParam для извлечения параметров запроса из компонента Query URL запроса:

@Path("smooth")
@GET
public Response smooth(
        @DefaultValue("2") @QueryParam("step") int step,
        @DefaultValue("true") @QueryParam("min-m") boolean hasMin,
        @DefaultValue("true") @QueryParam("max-m") boolean hasMax,
        @DefaultValue("true") @QueryParam("last-m") boolean hasLast,
        @DefaultValue("blue") @QueryParam("min-color") ColorParam minColor,
        @DefaultValue("green") @QueryParam("max-color") ColorParam maxColor,
        @DefaultValue("red") @QueryParam("last-color") ColorParam lastColor
        ) { ... }

Если параметр запроса step существует в URI запроса, значение step будет извлечено и проанализировано как 32-разрядное целое число со знаком и присвоено параметру метода step. Если step не существует, параметру метода step будет присвоено значение по умолчанию, равное 2, как объявлено в аннотации @DefaultValue. Если значение step не может быть приведено к 32-разрядному целое число со знаком, возвращается ответ HTTP 400 («Client Error»).

Пользовательские типы Java могут использоваться в качестве параметров запроса. В следующем примере кода показан класс ColorParam, использованный в предыдущем примере параметра запроса:

public class ColorParam extends Color {
    public ColorParam(String s) {
        super(getRGB(s));
    }

    private static int getRGB(String s) {
        if (s.charAt(0) == '#') {
            try {
                Color c = Color.decode("0x" + s.substring(1));
                return c.getRGB();
            } catch (NumberFormatException e) {
                throw new WebApplicationException(400);
            }
        } else {
            try {
                Field f = Color.class.getField(s);
                return ((Color)f.get(null)).getRGB();
            } catch (Exception e) {
                throw new WebApplicationException(400);
            }
        }
    }
}

Конструктор для ColorParam принимает один параметр String.

И @QueryParam, и @PathParam могут использоваться только на следующих типах Java.

  • Все примитивные типы, кроме char.

  • Все классы-обёртки примитивных типов, кроме Character.

  • Любой класс с конструктором, который принимает один аргумент String.

  • Любой класс со статическим методом с именем valueOf(String), который принимает один аргумент String.

  • List<T>, Set<T> или SortedSet<T>, где T соответствует уже перечисленным критериям. Иногда параметры могут содержать более одного значения для одного и того же имени. Если это так, эти типы могут быть использованы для получения всех значений.

Если @DefaultValue не используется вместе с @QueryParam, а параметр запроса отсутствует в запросе, это значение будет пустой коллекцией для List, Set или SortedSet, null для других типов объектов и значением по умолчанию для примитивных типов.

Параметры пути URI извлекаются из URI запроса, а имена параметров соответствуют именам переменных шаблона пути URI, указанным в аннотации на уровне класса @Path. Параметры URI указываются с помощью аннотации javax.ws.rs.PathParam в аргументах параметра метода. В следующем примере показано, как использовать переменные @Path и аннотацию @PathParam в методе:

@Path("/{username}")
public class MyResourceBean {
    ...
    @GET
    public String printUsername(@PathParam("username") String userId) {
        ...
    }
}

В предыдущем фрагменте имя переменной шаблона пути URI username указывается в качестве параметра для метода printUsername. Аннотация @PathParam устанавливается для переменной с именем username. Во время выполнения перед вызовом printUsername значение username извлекается из URI и приводится к String. Результирующая String затем доступна методу в виде переменной userId.

Если переменная шаблона пути URI не может быть приведена к указанному типу, среда выполнения JAX-RS возвращает клиенту ошибку HTTP 400 («Bad Request»). Если аннотация @PathParam не может быть приведена к указанному типу, среда выполнения JAX-RS возвращает клиенту ошибку HTTP 404 («Not Found»).

Параметр @PathParam и другие аннотации параметров (@MatrixParam, @HeaderParam, @CookieParam и @FormParam) подчиняются тем же правилам, что и @QueryParam.

Параметры cookie, указанные путём аннотирования параметра javax.ws.rs.CookieParam, извлекают информацию из файлов cookie, объявленных в заголовках HTTP, связанных с файлами cookie. Параметры заголовка, указанные аннотированием параметра javax.ws.rs.HeaderParam, извлекают информацию из заголовков HTTP. Параметры матрицы, указанные аннотированием параметра javax.ws.rs.MatrixParam, извлекают информацию из сегментов пути URL.

Параметры формы, указанные путём аннотирования параметра javax.ws.rs.FormParam, извлекают информацию из запроса с типом MIME application/x-www-form-urlencoded и соответствует кодировке, указанной в формах HTML, как описано в http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1. Этот параметр очень полезен для извлечения информации, отправляемой POST в HTML-формах.

В следующем примере извлекается параметр формы name из данных формы POST:

@POST
@Consumes("application/x-www-form-urlencoded")
public void post(@FormParam("name") String name) {
    // Сохранение сообщения
}

Чтобы получить общее отображение (Map) имён параметров и их значений из запроса, используйте следующий код:

@GET
public String get(@Context UriInfo ui) {
    MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
    MultivaluedMap<String, String> pathParams = ui.getPathParameters();
}

Следующий метод извлекает имена и значения параметров заголовка и cookie в отображение (Map):

@GET
public String get(@Context HttpHeaders hh) {
    MultivaluedMap<String, String> headerParams = hh.getRequestHeaders();
    Map<String, Cookie> pathParams = hh.getCookies();
}

В общем, @Context может использоваться для получения контекстных типов Java, связанных с запросом или ответом.

Для параметров формы можно сделать следующее:

@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
    // Сохранение сообщения
}

Конфигурирование приложений JAX-RS

Приложение JAX-RS состоит как минимум из одного класса ресурсов, упакованного в WAR-файл. Базовый URI, из которого ресурсы приложения отвечают на запросы, можно установить одним из двух способов:

  • Использование аннотации @ApplicationPath в дочернем классе javax.ws.rs.core.Application, упакованном в WAR

  • Использование тега servlet-mapping в дескрипторе развёртывания WAR web.xml

Здесь рассматриваются следующие темы:

Конфигурирование приложения JAX-RS с использованием дочернего класса Application

Создайте дочерний класс javax.ws.rs.core.Application для ручной настройки среды, в которой запускаются ресурсы REST, определённые в ваших классах ресурсов, включая базовый URI. Добавьте аннотацию @ApplicationPath на уровне класса, чтобы установить базовый URI.

@ApplicationPath("/webapi")
public class MyApplication extends Application { ... }

В предыдущем примере базовый URI установлен в /webapi, что означает, что все ресурсы, определённые в приложении, относятся к /webapi.

По умолчанию, будут обрабатываться все ресурсы в архиве. Переопределите метод getClasses, чтобы вручную зарегистрировать классы ресурсов в приложении во время выполнения JAX-RS.

@Override
public Set<Class> getClasses() {
    final Set<Class> classes = new HashSet<>();
    // регистрация корневого ресурса
    classes.add(MyResource.class);
    return classes;
}

Настройка базового URI в web.xml

Базовый URI для приложения JAX-RS можно установить с помощью тега servlet-mapping в дескрипторе развёртывания web.xml, используя имя класса Application в качестве сервлета.

<servlet-mapping>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <url-pattern>/webapi/*</url-pattern>
</servlet-mapping>

Этот параметр также переопределяет путь, заданный @ApplicationPath при использовании дочернего класса Application.

<servlet-mapping>
   <servlet-name>com.example.rest.MyApplication</servlet-name>
   <url-pattern>/services/*</url-pattern>
</servlet-mapping>

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