
- •Введение
- •1 Тема 1. Предметная область и терминология РСОС
- •1.1 Этапы развития распределенных систем
- •1.1.1 Классификация систем обработки данных
- •1.1.2 Распределенные вычислительные сети
- •1.1.3 Объектные распределенные системы
- •1.2 Становление систем с сервис-ориентированной архитектурой
- •1.2.1 Развитие web-технологий
- •1.2.2 Развитие концепции SOA
- •1.3 Современные парадигмы сервис-ориентированных архитектур
- •1.3.1 Эталонная модель SOA
- •1.3.2 Модель Захмана
- •1.3.3 Концепция среды открытой системы
- •1.3.4 Бизнес-парадигма модели SOA
- •1.4 Программная платформа Java Enterprise Edition
- •1.4.1 Контейнеры и компоненты Java EE
- •1.4.2 Служебные сервисы контейнеров
- •1.4.3 Артефакты контейнеров
- •1.4.4 Аннотации и дескрипторы развертывания
- •1.4.5 Управляемые компоненты платформы Java EE
- •1.5 Инструментальные средства реализации РСОС
- •1.5.1 Сервера приложений
- •1.5.2 Микросервисы
- •1.5.3 Apache Maven — сетевая сборка приложений
- •1.5.4 Eclipse Enterprise Edition
- •1.5.5 Тестовый пример
- •1.6 Заключение по первой главе
- •1.6.1 Итоги теоретических построений первой главы
- •1.6.2 Тематический план последующих глав
- •Вопросы для самопроверки
- •2 Тема 2. Использование компоненты JSF контейнера Web
- •2.1.1 Языки HTML, JavaScript и протокол HTTP
- •2.1.2 Серверные технологии PHP и HttpServlet
- •2.1.3 Технология AJAX и компонента JavaServer Faces
- •2.2 Шаблон проектирования MVC
- •2.2.1 Контроллер FacesServlet и жизненный цикл запроса
- •2.2.2 Контекст состояния запроса FacesContext
- •2.2.3 Модель в виде компонентов-подложек
- •2.2.4 Представление (View) средствами Facelets
- •2.2.5 JSF OmniFaces
- •2.3 Реализация тестового примера средствами JSF
- •2.3.1 Создание Facelets-шаблона изучаемой дисциплины
- •2.3.2 Прямая реализация тестового примера
- •2.4 Реализация уровня интерфейса сервисов
- •2.4.2 Компонента Users с ЖЦ @ApplicationScoped
- •2.4.3 Компонента RSOS с ЖЦ @SessionScoped
- •2.4.4 Компоненты-подложки с ЖЦ @RequestScoped
- •2.4.5 Приложение авторизации пользователя
- •2.4.6 Компонента подзаголовка проекта
- •2.4.7 Компонента меню лабораторных работ
- •2.4.8 Второй вариант меню лабораторных работ
- •Вопросы для самопроверки
- •3 Тема 3. Современные способы доступа к данным
- •3.1 Учебная инфраструктура темы
- •3.1.1 Учебная задача Letters (Письма)
- •3.1.2 Корпоратиные EJB-компоненты
- •3.1.3 Тестовый HttpServlet проекта lab4
- •3.1.4 Инфраструктура сервера TomEE и СУБД Derby
- •3.2 Технология JPA
- •3.2.1 Сущности
- •3.2.2 Объектно-реляционное отображение
- •3.2.3 Манеджер сущностей
- •3.2.4 Пример использования не-JTA-типа транзакций
- •3.3 Транзакции управляемые контейнером
- •3.3.1 Объектно-ориентированные запросы Criteria API
- •3.3.2 Реализация EJB-компонента с JTA-типом транзакций
- •3.3.3 Реализация JPA-сервлета
- •Вопросы для самопроверки
- •4 Тема 4. Обработка документов XML и JSON
- •4.1 Технология JAXB
- •4.1.1 Программное обеспечение технологии JAXB
- •4.1.2 Аннотации для связывания объектов Java
- •4.1.3 Преобразование объекта Java в документ XML
- •4.2 Технология JSON
- •4.2.1 Программное обеспечение технологии JSON
- •4.2.2 Преобразование объекта Java в документ JSON
- •4.2.3 Пример представления JSON на уровне классов
- •4.2.4 Выводы по результатам изучения главы 4
- •Вопросы для самопроверки
- •5 Тема 5. Web-службы SOAP
- •5.1.1 Протоколы и языки Web-служб
- •5.1.2 Краткое описание языка WSDL
- •5.1.3 Краткое описание протокола SOAP
- •5.1.4 Необязательный реестр Web-служб — UDDI
- •5.1.5 Программные пакеты Java EE, обслуживающие SOAP
- •5.2 Создание Web-служб SOAP
- •5.2.1 Подготовка проекта lab7
- •5.2.2 Аннотации поставщика Web-сервиса
- •5.2.3 Обработка исключений поставщика Web-сервиса
- •5.2.4 Обработка контекста Web-сервиса
- •5.3 Создание потребителя Web-службы SOAP
- •5.3.1 Аннотации для потребителей сервиса
- •5.3.2 Использование утилиты wsimport
- •5.3.3 Реализация тестового примера
- •5.3.4 Выводы по результатам изучения главы 5
- •Вопросы для самопроверки
- •6 Тема 6. Web-службы в стиле REST
- •6.1 Основные положения технологии RESTful
- •6.1.1 Ресурсы, URI, представления и адресуемость
- •6.1.2 Протокол HTTP
- •6.1.3 Языки WADL и HAL
- •6.1.4 Технология JAX-RS
- •6.2 Реализация Web-службы в стиле REST
- •6.2.1 Преобразование сущности Letter
- •6.2.2 Реализация EJB-компоненты Lets9
- •6.2.3 Получение списка записей в формате XML
- •6.2.4 Получение записи по номеру индентификатора
- •6.2.5 Добавление новой записи
- •6.3 Вызов Web-служб в стиле REST
- •6.3.1 Инструментальные средства потребителя сервиса
- •6.3.2 Полная реализация RESTfull-сервиса
- •6.3.3 Шаблон реализации потребителя сервиса
- •6.3.4 Клиент, реализующий методы GET и POST
- •6.3.6 Клиент, реализующий методы DELETE и PUT
- •Вопросы для самопроверки
- •Заключение
- •Список использованных источников
- •Алфавитный указатель

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