Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Распределенные сервис-ориентированные системы..pdf
Скачиваний:
16
Добавлен:
05.02.2023
Размер:
9.2 Mб
Скачать

6.1.4 Технология JAX-RS

Программная платформа Java EE обеспечивает полную поддержку технологии RESTful с помошью инструментальных средств проекта JAX-RS.

JAX-RS (Java API for RESTful Web Services) — это спецификация API языка программирования Java, обеспечивающая поддержку создания Web-сервисов в соответствии с архитектурным шаблоном передачи состояния представления REST. Не имеет своего RFC, но содержит достаточно полное описание для версии 2.0 от 22 мая 2013 года, представленное корпорацией Oracle. Его можно найти в источнике [30], а полный перечень пакетов технологи JAX-RS, включающий как серверную, так и клиентскую части, представлен в таблице 6.2.

Таблица 6.2 — Основные пакеты JAX-RS [17]

Пакет

Описание пакета

javax.ws.rs

Высокоуровневые интерфейсы и аннотации, используемые для

 

создания Web-служб с передачей состояния представления.

javax.ws.rs.client

Классы и интерфейсы клиентского API JAX-RS.

javax.ws.rs.container

API JAX-RS контейнера.

javax.ws.rs.core

Низкоуровневые интерфейсы и аннотации, используемые для

 

создания Web-ресурсов с передачей состояния представления.

javax.ws.rs.ext

API, предоставляющие расширения для типов, поддерживаемых

 

в JAX-RS API.

Все спецификации JAX-RS основаны только на аннотациях и не требуют дескриторов развертывания в формате XML-файлов.

RESTful-сервис реализуется специальным сервлетом, который представляет собой обычный JAVA-класс, аннотированный аннотацией @Path(...) и одной из дополнительных аннотаций @Stateless или @Singleton.

RESTful-сервис использует достаточно много аннотаций, определенных в пакете javax.ws.rs. Наиболее важные из них, влияющие на общую архитектуру реализации сервиса, представлены в таблице 6.3.

Аннотации @GET, @PUP, @POST, @DELETE и @HEAD указывают допустимые типы запросов к RESTful-сервису, а аннотации @Produces(…) и @Consumes(…) — указывают типы ответов и запросов, представленные в виде констант их аргументов.

Медиатипы запросов и ответов определены в соответствующем классе javax.ws.rs.core.MediaType, а их значения представлены в таблице 6.4.

242

Таблица 6.3 — Основные пакеты JAX-RS [17]

Аннотация

Описание

@Path(...)

Указывает относительный путь для класса или метода

 

ресурса.

@GET, @PUP, @POST,

Указывают тип HTTP-запроса, разделяя ПО сервиса на

@DELETE и @HEAD

соответствующие части.

@Produces(...)

Указывает тип ответа (см. таблицу 6.4).

@Consumes(...)

Указывает принимаемый тип запроса (см. таблицу

 

6.4).

Таблица 6.4 — MIME-типы класса MediaType [17]

Имя константы

MIME-тип

APPLICATION_ATOM_XML

"application/atom+xml"

APPLICATION_FORM_URLENCODED

"application/x-www-form-urlencoded"

APPLICATION_JSON

"application/json"

APPLICATION_OCTET_STREAM

"application/octet-stream"

APPLICATION_SVG_XML

"application/svg+xml"

APPLICATION_XHTML_XML

"application/xhtml+xml"

APPLICATION_XML

"application/xml"

MULTIPART_FORM_DATA

"multipart/form-data"

TEXT_HTML

"text/html"

TEXT_PLAIN

"text/plain"

TEXT_XML

"text/xml"

WILDCARD

"*/*"

Главной аннотацией, по которой контейнер определяет тип RESTful-сер- влета, является аннотация @Path(...), имеющая общий формат:

@Path("/Путь1/Путь2/.../ПутьN")

где ПутьK — слово, задающее часть пути и соответсвующие части path, определенные ранее в адресе URI. Это слово также может быть представлено регулярным выражением, которое контролируется контейнером сервиса, в формате:

"{" variable-name [ ":" regular-expression ] "}"

Чтобы продемонстрировать сказанное более наглядно, создадим в среде

243

Eclipse EE проект типа Dynamic Web Project с именем lab9, не забыв указать создание файла web.xml.

В указанном проекте создадим класс LetsRestService, который будем рассматривать как шаблон, демонстрирующий работу со списком записей типа Letter, рассмотренных ранее в предыдущих главах.

С учетом изученных аннотаций и условий отображения результатов сервиса в приложении браузера, указанный шаблон может быть представлен, как показано на листинге 6.1.

Листинг 6.1 — Исходный текст класса LetsRestService.java для проекта lab9

package rsos.lab9;

import javax.ejb.Stateless; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces;

import javax.ws.rs.core.MediaType;

/**

*Аннотации, определяющие сервлет типа RESTful, который

*доступен по адресу: http://localhost:8080/lab9

*/ @Path("/") @Stateless

public class LetsRestService

{

// Простой тест работоспособности REST-сервиса /**

*Простейшая демонстрация доступа по методу GET, доступная

*по адресу: http://localhost:8080/lab9/test

*/

@GET @Path("/test")

@Produces(MediaType.TEXT_PLAIN) public String testRS()

{

return "Проверка технологии JAX-RS";

}

//Получение списка записей

/**

* Доступ по методу GET, читающий весь список записе, при * обращении по адресу: http://localhost:8080/lab9/letter */

@GET @Path("/letter")

@Produces(MediaType.TEXT_PLAIN) public String getLets()

{

return "Получение списка записей - не реализовано!";

}

//Получение записи по идентификатору id=1

244

/**

*Доступ по методу GET, читающий только одну запись, при

*обращении по адресу: http://localhost:8080/lab9/letter/1

*Должен использоваться один параметр типа int.

*/

@GET @Path("/letter/1")

@Produces(MediaType.TEXT_PLAIN) public String getLetter()

{

return "Получение записи по идентификатору - не реализовано!";

}

//Добавление новой записи @POST

@Path("/add") @Produces(MediaType.TEXT_PLAIN) public String addLetter()

{

return "Добавление новой записи - не реализовано!";

}

//Удаление записи по идентификатору

@POST @Path("/delete")

@Produces(MediaType.TEXT_PLAIN) public String deleteLetter()

{

return "Удаление записи по идентификатору - не реализовано!";

}

// Модификация записи по идентификатору @POST

@Path("/mod") @Produces(MediaType.TEXT_PLAIN) public String modLetter()

{

return "Модификация записи по идентификатору - не реализовано!";

}

}

Следует обратить внимание, что приведенный шаблон сервлета содержит только аннотации обработки запросов типа GET и POST. Это сделано для того, чтобы его работу можно было проверить с помощью приложения браузера.

Для демонстрации того, что класс LetsRestService является RESTful-сер- висом, создадим в каталоге WebContent нашего проекта HTML-файл с именем index.html, как это показано на листинге 6.2.

Листинг 6.2 — Исходный файла index.html проекта lab9

<!DOCTYPE html> <html>

<head>

<meta charset="UTF-8"> <title>Тест lab9</title>

</head> <body>

245

<h2>Тестирование приложения типа JAX-RS</h2> <hr>

<a href="http://localhost:8080/lab9/test"> Проверка связи с сервисом: .../lab9/test</a> <hr>

<a href="http://localhost:8080/lab9/letter"> Получение списка записей: .../lab9/letter</a>

<hr>

Получение записи по идентификатору: .../lab9/letter/1 <form name="f0" action="http://localhost:8080/lab9/letter/1"

method="get" accept-charset="UTF-8">

<input type="text" size="6"> <input type="submit">

</form> <hr>

Добавление новой записи: .../lab9/letter <br>

<form name="f1" action="http://localhost:8080/lab9/letter" method="post" accept-charset="UTF-8">

<textarea rows="2" cols="40" name="text"></textarea> <input type="submit">

</form> <hr>

Удаление записи по идентификатору: .../lab9/delete

<form name="f2" action="http://localhost:8080/lab9/delete" method="post" accept-charset="UTF-8">

<input type="text" size="6"> <input type="submit">

</form> <hr>

Модификация записи по идентификатору: .../lab9/mod <form name="f3" action="http://localhost:8080/lab9/mod"

method="post" accept-charset="UTF-8">

<input type="text" size="6">

<textarea rows="2" cols="40" name="text"></textarea> <input type="submit">

</form> <hr>

</body> </html>

Обратите внимание, что получение списка записей и добавление новой записи осуществляются по одному адресу http://localhost:8080/lab9/letter, но разными методами GET и POST.

Теперь, если в проекте lab9 выделить вкладку с файлом index.html и запустить сервер, то мы получим окно браузера для тестовых испытаний, что показано на рисунке 6.1.

246

Рисунок 6.1 — Окно браузера для тестовых испытаний сервлета LetsRestService

Если активировать ссылку «Проверка связи с сервером: .../lab9/test», то получим результат, показанный на рисунке 6.2.

Рисунок 6.2 — Ответ сервлета LetsRestService

Другие ссылки файла index.html возвратят аналогичный результат, хотя и с другим содержанием, соответствующим назначению этих ссылок.

Таким образом, работоспособность сервиса RESTful — вполне показана представленными примерами.

Общий адекватный ответ RESTful-сервиса формируется с помощью специального класса javax.ws.rs.core.Response.

В приведенном выше шаблоне класса LetsRestService, формат ответа

247

представлен в виде обычного текста, что определяется и обеспечивается соответсвующей аннотацией @Produces(MediaType.TEXT_PLAIN). Для корректного формирования ответа сервера, необходимо использовать объект класса Response, который учитывает все особенности функционирования протокола HTTP. В таблице 6.5 представлены основные методы этого класса, используемые для указанной цели.

Таблица 6.5 — Основные методы класса Response [17]

Метод

Описание

accepted()

Создает новый объект ResponseBuilder с состоянием: 202 —

 

Принято.

created()

Создает новый объект ResponseBuilder для созданного ресурса, с

 

использованием его URI.

noContent()

Создает новый объект ResponseBuilder для пустого ответа.

notModified()

Создает новый объект ResponseBuilder с состоянием: 304 — Не

 

изменялось.

ok()

Создает новый объект ResponseBuilder с состоянием: 200 —

 

Хорошо.

serverError()

Создает новый объект ResponseBuilder с состоянием: 500 —

 

Серверная ошибка.

status()

Создает новый объект ResponseBuilder с предоставленным

 

состоянием.

temporaryRedirect()

Создает новый объект ResponseBuilder с временным перенап-

 

равлением.

getCookies()

Получает cookie из сообщения ответа.

getHeaders()

Получает заголовки из сообщения ответа.

getLinks()

Получает ссылки, прикрепленные к сообщению в заголовке.

getStatus()

Получает код состояния, ассоциированный с ответом.

readEntity()

Получает объект сообщения, как экземпляр указанного типа Java,

 

используя интерфейс MessageBodyReader, поддерживающий

 

отображение сообщения на запрошенный тип.

Уже представленный перечень аннотаций показывает достаточно проработанный инструментарий проекта JAX-RS. К ним необходимо еще добавить:

а) список аннотаций параметров запроса: @DefaultValue, @PathParam,

@QueryParam, @FormParam, @MatrixParam, @HeaderParam и @CookieParam;

б) @Context — аннотация, возвращающая весь контекст объекта запроса.

Учитывая достаточно большой объем имеющихся наработок, ограничимся только рядом примеров, рассмотренных в следующем подразделе.

248