
- •Введение
- •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
- •Вопросы для самопроверки
- •Заключение
- •Список использованных источников
- •Алфавитный указатель

.build();
}
}
Этим кодом мы завершаем разработку проекта lab9, соотвествующего Web-службе поставщика сервиса.
Дальнейшие пункты данной главы посвящены приложению, реализующему функционал потребителя RESTful-сервиса.
6.3.3 Шаблон реализации потребителя сервиса
Полная реализация RESTful-сервиса требует размещение функционала потребителя сервиса на сервере приложений.
Поскольку браузеры ориентированы только на HTTP-запросы GET и POST, нам необходимо серверное приложение, которое бы обеспечивало полную функциональность потребителя RESTful-сервиса.
В качестве основы такого приложения можно взять проект labs, рассмотренный во второй главе и реализующий прототип учебного приложения по всем лабораторным работам данной дисциплины (см. подраздел 2.4). Хотя полная реализация этого проекта была отложена по причине очевидного усложнения учебных примеров, реализуемых в главах 3 - 5, тем не менее, для демонстрации агента потребителя сервиса Web-службы в стиле REST этот проект вполне подходит.
Напомню, что проект labs обеспечивает доступ к серверу приложений посредством адресации XHTML-файла соответствующей лабораторной работы (см. последний вариант реализации, описанный в пункте 2.4.8 и показанный на рисунке 2.32). В частности, работе №9 соответствует файл lab9.xhtml. Если за начальное представление этого файла взять содержимое листинга 6.12, то, после запуска проекта и авторизации пользователем upk, внешний вид окна браузера будет отображен рисунком 6.11.
Листинг 6.12 — Исходное содержимое файла lab9.xhtml проекта labs
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core" xmlns:f="http://xmlns.jcp.org/jsf/core" xml:lang="ru">
<ui:composition template="/WEB-INF/templates/lab3Templ.xhtml">
<!-- Переопределение контекстной страницы context -->
272

<ui:define name="context">
<div align="left" style="color:black;padding:10px"> <b>lab9.xhtml - работа с сервисом: http://localhost:8080/lab9/letter</b>
<hr/> </div>
</ui:define>
</ui:composition>
</html>
Рисунок 6.11 — Начальное отображение файла lab9.xhtml
Обратите внимание, что XHTML-ресурс lab9.xhtml не имеет активных элементов и еще не использует никакую компонету-подложку. Другими словами
— это всего лишь «заглушка» для будущей реализации соответствующего проекта.
Вполне разумно для реализации шаблона потребителя сервиса использовать компонент-подложку с именем Lab9.java, что создаст нужную семантическую ассоциацию при описании проекта.
Следующим шагом необходимо решить: какой функционал и область действия должна обеспечивать эта подложка Lab9.java.
273

Чтобы правильно ответить на данный вопрос, студенту рекомендуется перечитать подраздел 2.4 второй главы. Особое внимание здесь необходимо обратить на пункт 2.4, где на рисунке 2.26 (см. стр. 114) представлена схема взаимодействия браузера и компонент-подложек JSF проекта labs.
Для болшей наглядности изложения учебного материала, повторим отображение этого рисунка здесь, в виде рисунка 6.12.
Браузер
клиента
<Web-ресурс> |
|
<Web-ресурс> |
|
<Web-ресурс> |
|||
auth3.xhtml |
|
subheader3.xhtml |
|
menus3.xhtml |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Запрос> |
|
<Запрос> |
|
<Запрос> |
|||
Auth3.class |
|
SubHeader3.class |
|
Menus3.class |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Сессия> |
|
|
|
|
|
|
|
RSOS.class |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Приложение> |
|
|
|
|
|
|
|
Users.class |
|
|
|
Рисунок 6.12 — Повторное отображение рисунка 2.26 главы 2, стр. 114
Хорошо видно, что все представленные XHTML-ресурсы имеют ком- поненты-подложки с областью действия @RequestScoped. Это связано с тем, что они обслуживают локальные запросы к данным, которые храняться в CDIкомпоненте RSOS.class c областью действия @SessionScoped.
Особенность создаваемой здесь компоненты-подложки Lab9.class состоит в необходимости доступа к удаленным данным, реализуемым поставщиком сервиса в виде проекта lab9, и сохранении этих данных для отображения их с помощью XHTML-ресурса lab9.xhtml.
Из сказанного следует, что компонента Lab9.class должна обслуживать отдельного пользователя в течение всей сессии и иметь соответствующую аннотацию. Более того, эта компонента должна сохранять следующие данные:
274

а) resMsg — текстовое сообщение, соответствующее полученному объекту типа Response;
б) list — список прочитанных сообщений типа List<Letter>;
в) id — целочисленный идентификатор запроса объекта типа Letter; г) text — текстовое сообщение запроса для объекта типа Letter;
д) rsos — инъекция сессионного объекта типа RSOS для получения данных о пользователе, выполняемой работе и результате авторизации;
е) address — текстовая константа http://localhost:8080/lab9/letter, соответствующая базовому адресу удаленного ресурса, который представлен сервером проекта lab9.
Естественно, что компонента Lab9.class должна иметь соответствующий набор методов (геттеров и сеттеров), обслуживающих доступ к данным из XHTML-ресурса lab9.xhtml.
Клиентская часть потребителя сервиса должна иметь описания классов Letter и ListLets.
Действительно, поставщик сервиса, представленный Web-сервисом класса LetsRestService (см. листинг 6.11, стр. 272-276), возвращает объекты типа Letter и ListLets в формате JSON. Соответственно, клиентская сторона в виде класса Lab9 должна восстанавливать эти объекты. Поэтому описания этих классов должны присутствовать в проекте labs, но в клиентском исполнении, как это показано на листингах 6.13 - 6.14.
Листинг 6.13 — Клиентское описание класса Letter.java проекта labs
package asu.rsos;
import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.Date;
import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType;
/**
*Клиентская часть базовой сущности Letter.
*Добавляются: обязательная аннотация @XmlRootElement
*и @XmlType(...)
*/
@XmlType(propOrder={"id", "date", "name", "text"}) @XmlRootElement
public class Letter implements Serializable
{
275
// Идентификатор сериализации
private static final long serialVersionUID = 1L;
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id;
private Date date; private String name; private String text;
/** * Конструкторы, геттеры, сеттеры и другие бизнес-методы */
public Letter() {
}
public Letter(Date date, String name, String text) { this.date = date;
this.name = name; this.text = text;
}
// Геттеры и сеттеры POJO-класса /**
*Аннотация @XmlElement для публичного метода
*getId()
*/
@XmlElement
public int getId() { return id;
}
public void setId(int id) { this.id = id;
}
/**
*Аннотация @XmlElement для публичного метода
*getDate()
*/
@XmlElement
public Date getDate() { return this.date;
}
public void setDate(Date date) { this.date = date;
}
/**
*Аннотация @XmlElement для публичного метода
*getName()
*/
@XmlElement
public String getName() { return name;
}
public void setName(String name) { this.name = name;
276
}
/**
*Аннотация @XmlElement для публичного метода
*getText()
*/
@XmlElement
public String getText() { return text;
}
public void setText(String text) { this.text = text;
}
// Дополнительные функции форматирования public String toString() {
return Integer.toString(id) + " " + date.toString() + " " + name + " " + text;
}
public String getDateString() { SimpleDateFormat sdf =
new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); return sdf.format(this.date);
}
}
Листинг 6.14 — Клиентское описание класса ListLets.java проекта labs
package asu.rsos;
import java.io.Serializable; import java.util.ArrayList; import java.util.List;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement;
/**
*Корневая аннотация для всего класса, задающая
*имя списка объектов типа Letter.
*/ @XmlRootElement(name="letters")
public class ListLets implements Serializable
{
private static final long serialVersionUID = 1L;
// Приватная переменная класса
private List<Letter> list = new ArrayList<>(); /**
* Конструкторы, геттеры, сеттеры и другие бизнес-методы */
public ListLets() {}
public ListLets(Letter letter) { if(letter != null)
list.add(letter);
}
277

public ListLets(List<Letter> list) { this.list = list;
}
/**
*Аннотация для публичного метода getList(), задающая имя для
*описания объекта типа Letter и допускающая пустой список. */
@XmlElement(name="letter", nillable = true) public List<Letter> getList() {
return list;
}
}
Учитывая изложенное выше, главную часть схемы взаимодействия браузера, локальных агентов потребителя сервиса и удаленного сервера приложений поставщика сервиса можно представить рисунком 6.13.
|
|
|
|
|
|
Браузер |
|
|
|
|
|
|
||
|
|
|
|
|
|
клиента |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
Запросы- |
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
Ответы |
|
|
|
|
|
|
|
|
|
HTTP |
||||||
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Web-ресурс> |
|
|
|
|
|
|
||
|
Проверка |
|
lab9.xhtml |
|
|
|
|
|
|
|||||
|
авторизации |
|
|
|
|
|
|
|
|
Сервер приложений |
||||
геттеры |
|
сеттеры |
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
Проект lab9 |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
<Сессия> |
|
|
|
<Сессия> |
|||||||||
|
|
|
|
|
|
|
|
|
|
|||||
|
RSOS.class |
|
|
|
Lab9.class |
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рисунок 6.13 — Схема взаимодействия потребителя с поставщиком сервиса
Как видно из рисунка, сессионная компонента Lab9.class должна обеспечивать функционал трех видов:
1)isAuth() — метод запрашивающий результат авторизации пользователя и выбор работы - «Работа №9»;
2)геттеры/сеттеры — стандартные методы, обслуживающие запросы Web-ресурса lab9.xhtml;
3)mGetList(), mGetLetter(), mPostLetter(), mDeleteLetter() и mPutLetter() —
методы, осуществояющие распросы к удаленному серверу приложений и возвращающие строку «lab9», что означает переход к Web-ресурсу lab9.xhtml.
Сучетом введенных ограничений, шаблон реализуемой компоненты Lab9.class представлен на листинге 6.15.
278
Листинг 6.15 — Шаблон файла Lab9.java проекта labs
package asu.rsos;
import java.io.Serializable; import java.util.ArrayList; import java.util.List;
import javax.enterprise.context.SessionScoped; import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget;
/**
*Компонент-подложка ресурса lab9.xhtml, обеспечивающая
*CRUD-операции потребителя сервиса, посредством запросов
*GET, POST, DELETE и PUT к Web-сервису проекта lab9.
*/
@Named
@SessionScoped public
class Lab9 implements Serializable
{
/** * Стандартный идентификатор для сериализации */
private static final long serialVersionUID = 1L; /**
* Инъекция объекта класса RSOS */
@Inject
private RSOS rsos; /**
*Приватные переменные, обслуживаемые методами
*геттеров и сеттеров.
*/
//Текстовое сообщение, соответствующее ответу типа Response private String resMsg = "Вводите запросы...";
//Прочитанный список сообщений
private List<Letter> list = new ArrayList<>();
// Идентификатор обрабатываемого сообщения private int id;
//Текст обрабатываемого сообщения private String text;
//Адрес доступа к сервису ListRestService проекта lab9 private String address = "http://localhost:8080/lab9/letter"; /** * Пустой конструктор */
public Lab9() {} /**
* Публичные методы геттеров и сеттеров
*/
public String getResMsg() {return resMsg;}
public void setResMsg(String resMsg) {this.resMsg = resMsg;}
public List<Letter> getList() {return list;}
279
// |
public void |
setList(List<Letter> |
list) {this.list = list;} |
|
public int |
getId() {return id;} |
|
|
public void |
setId(int id) {this.id = id;} |
|
|
public String getText() {return text;} |
||
|
public void |
setText(String text) |
{this.text = text;} |
|
public String getAddress() {return |
address;} |
|
|
public void |
setAddress(String address) {this.address = address;} |
/** * Метод проверки авторизации */
public boolean isAuth()
{
if(rsos.getUser() == null || rsos.getWork() == null) return false;
if(rsos.getUser().length() > 0
|| "Работа №9".equals(rsos.getWork())) return true;
return false;
}
/**
*Шаблоны методов, реализующих запросы к поставщику сервисов.
*Все они должны возвращать строку "lab9", что возвращает
*запрос к ресурсу lab9.xhtml.
*/
//Получить список объектов типа Letter public String mGetList() {
resMsg = "Метод GET - не реализован"; return "lab9";
}
// Получить объект типа Letter по идентификатору id public String mGetLetter() {
resMsg = "Метод GET - не реализован"; return "lab9";
}
//Создать новый объект типа Letter public String mPostLetter() {
resMsg = "Метод POST - не реализован"; return "lab9";
}
//Удалить объект типа Letter по идентификатору id public String mDeleteLetter() {
resMsg = "Метод DELETE - не реализован"; return "lab9";
}
//Модифицировать объект типа Letter по идентификатору id public String mPutLetter() {
resMsg = "Метод PUT - не реализован"; return "lab9";
}
}
280
Обратите внимание, что на приведенном листинге шаблона компонентыподложки Lab9 нереализованными являются только пять последних методов, отвечающих за запросы к Web-сервису проекта lab9. Ими мы займемся в следующих пунктах данного подраздела, а сейчас преобразуем ресурс lab9.xhtml к виду, показанному на листинге 6.16.
Листинг 6.16 — Итоговое содержимое файла lab9.xhtml проекта labs
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:c="http://xmlns.jcp.org/jsp/jstl/core" xmlns:f="http://xmlns.jcp.org/jsf/core" xml:lang="ru">
<ui:composition template="/WEB-INF/templates/lab3Templ.xhtml">
<!-- Переопределение контекстной страницы context --> <ui:define name="context">
<div align="left" style="color:black;padding:10px"> <b>lab9.xhtml - работа с сервисом: http://localhost:8080/lab9/letter</b>
<hr/>
<h:outputText value="#{lab9.resMsg}" style="color:red"/> <hr/>
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Идентификатор:"/> <h:inputText value="#{lab9.id}"/>
<h:outputText value="Введи текст:"/>
<h:inputTextarea value="#{lab9.text}" rows="5" cols="40"/> </h:panelGrid>
<h:commandButton value="GET-список" action="#{lab9.mGetList()}"/> <h:commandButton value="GET-письмо" action="#{lab9.mGetLetter()}"/> <h:commandButton value="POST-новое" action="#{lab9.mPostLetter()}"/> <h:commandButton value="DELETE-письмо" action="#{lab9.mDeleteLetter()}"/> <h:commandButton value="PUT-письмо" action="#{lab9.mPutLetter()}"/>
</h:form><hr/>
<table id="table1" cellspacing="0" cellpadding="5" border="0" > <thead><tr>
<th align="left" >№</th> <th align="left" >Дата</th>
<th align="left" >Пользователь</th> <th align="left" >Сообщение</th>
</tr></thead>
<tbody>
<c:forEach items="${lab9.list}" var="letter">
281

<tr> |
|
<td><h:outputText value="${letter.id}" default="*" |
/></td> |
<td><h:outputText value="${letter.dateString}" |
/></td> |
<td><h:outputText value="${letter.name}" |
/></td> |
<td><h:outputText value="${letter.text}" |
/></td> |
</tr> |
|
</c:forEach> |
|
</tbody> |
|
</table> |
|
</div> |
|
</ui:define> |
|
</ui:composition> |
|
</html> |
|
Результат отображения ресурса, представленного данным листингом, показан на рисунке 6.14.
Рисунок 6.14 — Начальное изображение ресурса lab9.xhtml
Теперь перейдем к решению конкретных задач.
282