
- •Введение
- •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
- •Вопросы для самопроверки
- •Заключение
- •Список использованных источников
- •Алфавитный указатель
4.1.3 Преобразование объекта Java в документ XML
Проведем демонстрацию теоретических рассуждений, изложенных в предыдущих двух пунктах, посредством реализации нескольких тестовых приложений.
Для этого, в инструментальной среде Eclipse создадим обычный Javaпроект с именем lab5. Откроем в нем новый класс с именем Letter и перенесем в него содержимое исходного текста, который представлен ранее на листинге 4.1. Далее, создадим новый Java-класс с именем Test1 и реализуем в нем алгоритм отображения объекта класса Letter в XML-файл с абсолюным имененем
/home/upk/lab5.Letter.xml.
Полная реализация класса Test1 со всеми необходимыми комментариями приведена на листинге 4.2.
Листинг 4.2 — Исходный текст класса Test1 проекта lab5
package rsos.lab5;
import java.io.File; import java.util.Date;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller;
public class Test1 {
public static void main(String[] args) throws JAXBException
{
// Создаем объект класса Letter Letter let1 =
new Letter(new Date(), "upk",
"Сообщение для lab5: приложение Test1");
let1.setId(20);
//Печатаем содержимое объекта let1 на консоль, используя
//переопределенный метод toString() класса Letter System.out.println("Объект let1=[" + let1 + "]\n");
//Создаем контекст технологии JAXB для класса Letter JAXBContext context =
JAXBContext.newInstance(Letter.class);
//Создаем объект маршалинга
Marshaller marsh = context.createMarshaller();
// Добавляем свойство форматированного вывода marsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
Boolean.TRUE);
181

//Выводим отображение объекта let1 на терминал marsh.marshal(let1, System.out);
//Создаем объект вывода в файл: /home/upk/lab5.Letter.xml File file =
new File(System.getenv("HOME") + "/lab5.Letter.xml");
//Выводим отображение объекта let1 в файл
marsh.marshal(let1, file);
}
}
Первый тест проведем, запустив класс Test1 на выполнение, причем в отображаемом классе Letter оставим только одну обязательную аннотацию @XmlRootElement (без параметра name). Убедимся, что отображение исследуемого класса записалось в файл lab5.Letter.xml, как это показано на рисунке 4.1.
Рисунок 4.1 — Прямое отображение класса Letter в файл lab5.Letter.xml
Обратите внимание, что все переменные класса Letter отобразились в файл со своими именами. Причем:
а) имя класса отобразилось в корневом теге и со строчной буквы;
б) переменные класса — id и date правильно отобразились тегами со своими именами, но поменялись местами.
Второй тест проведем, восстановив все аннотации класса Letter так, как они представлены на листинге 4.1.
Результат запуска второго теста представлен на рисунке 4.2, в виде изображения консоли инструментальной среды Eclipse.
Первой строкой на консоль выведено представление объекта let1 с помощью метода toString() класса Letter. Заметим, что этот метод является стандартным для системного вывода языка Java, а программисты используют его переопределения, когда им нужно контролировать содержимое сложных объектов.
182

Рисунок 4.2 — Полностью аннотированное отображение класса Letter
Далее, через пустую строку, выведено отображение объекта let1 для варианта полностью аннотированного класса Letter. Здесь можно отметить, что:
а) изменилось название корневого тега на <letter-object>; б) переменная класса id представлена как атирибут;
в) остальные переменные класса представлены как элементы своими тегами и в том порядке, как это указано в аннотации @XmlType(...).
Третий тест проведем с помощью запуска на выполнение класса Test2, исходный текст которого приведен на листинге 4.3 и который производит обратное отображение XML-файла lab5.Letter.xml в объект let2 класса Letter.
Листинг 4.3 — Исходный текст класса Test2 проекта lab5
package rsos.lab5;
import java.io.FileNotFoundException; import java.io.FileReader;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller;
public class Test2 {
public static void main(String[] args)
throws JAXBException, FileNotFoundException
{
// Создаем контекст технологии JAXB для класса Letter JAXBContext context =
JAXBContext.newInstance(Letter.class);
//Создаем объект демаршалинга Unmarshaller unmarsh =
context.createUnmarshaller();
//Создаем объект вода из файла: /home/upk/lab5.Letter.xml FileReader fileReader =
new FileReader(System.getenv("HOME") + "/lab5.Letter.xml");
183

//Водим отображение объекта let1 из файла:
///home/upk/lab5.Letter.xml
Letter let2 =
(Letter) unmarsh.unmarshal(fileReader);
//Печатаем содержимое объекта let2 на консоль, используя
//переопределенный метод toString() класса Letter System.out.println("Объект let2=[" + let2 + "]\n");
}
}
Запустив класс Test2 на выполнение, мы получим результат, показанный на рисунке 4.3.
Рисунок 4.3 — Обратное отображение класса Letter в объект let2
Хорошо видно, что объект let2 класса Letter полностью и точно востановлен из сохраненного отображения lab5.Letter.xml.
Обычно, данные в приложениях передаются списками.
Рассмотрим более сложное отображение объектов JAVA-классов. Для этого, рассмотрим класс ListLetters, содержащий две переменные:
1)name — имя или название списка;
2)list — список объектов класса Letter (возможно пустой).
Исходный и полностью аннотированный текст сериализованного класса ListLetters представим листингом 4.4.
Листинг 4.4 — Исходный текст класса ListLetters проекта lab5
package rsos.lab5;
import java.io.Serializable; import java.util.ArrayList; import java.util.List;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType;
@XmlType(propOrder={"name", "list"})
@XmlRootElement
184
public class ListLetters implements Serializable
{
private static final long serialVersionUID = 1L;
// Приватные переменные класса private String name;
private List<Letter> list = new ArrayList<>();
/** * Конструкторы, геттеры, сеттеры и другие бизнес-методы */
public ListLetters() {
}
public ListLetters(String name) { this.name = name;
}
@XmlElement
public String getName() { return name;
}
public void setName(String name) { this.name = name;
}
@XmlElementWrapper(name="list-letters", nillable = true) public List<Letter> getList() {
return list;
}
public void setList(List<Letter> list) { this.list = list;
}
// Дополнительная функция форматирования public String toString() {
String s0 = "ListLetters:name=" + name; for(Letter let : list)
{
s0 += "\n" + let.toString();
}
return s0;
}
}
Обратите внимание, что ListLetters представляет собой POJO-класс с двумя приватными переменными, поэтому аннотации выставляются перед публичными методами get*().
Добавилась новая аннотация @XmlElementWrapper(...), которая соотносится с переменной list вместо аннотации @XmlElement и вводит новое имя list-letters, которое будет «окружать» (wrapper) список объектов типа Letter.
У класса ListLetters имеется также собственный переопределенный метод
185

toString(), назначение которого — обеспечить системный вывод содержимого объекта на терминал (консоль). Этот метод не является обязательным, но очень полезен для наших учебных целей.
Теперь создадим тестовый класс Test3, обеспечивающий создание объекта list типа ListLetters, отображение этого объекта в XML-формат и запись полученного отображения в файл /home/upk/lab5.ListLetters.xml.
Сам объект list будет иметь собственное имя и содержать список из двух объектов типа Letter, как это показано на листинге 4.5.
Листинг 4.5 — Исходный текст класса Test3 проекта lab5
package rsos.lab5; import java.io.File;
import java.util.ArrayList; import java.util.Date; import java.util.List;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller;
public class Test3 {
public static void main(String[] args) throws JAXBException
{
//Создаем список из двух объектов класса Letter List<Letter> lets = new ArrayList<>();
//Первое сообщение
Letter letter =
new Letter(new Date(), "upk",
"Сообщение №21 для lab5:Test3");
letter.setId(21); lets.add(letter);
// Второе сообщение letter =
new Letter(new Date(), "asu",
"Сообщение №22 для lab5:Test3");
letter.setId(22); lets.add(letter);
//Создаем объект класса ListLetters ListLetters list =
new ListLetters("Список писем для приложения lab5:Test3"); list.setList(lets);
//Печатаем содержимое объекта list на консоль, используя
//переопределенный метод toString() класса ListLetters
System.out.println("Объект list\n----------- |
\n" + list + "\n"); |
// Создаем контекст технологии JAXB для класса ListLetters JAXBContext context =
JAXBContext.newInstance(ListLetters.class);
186

//Создаем объект маршалинга Marshaller marsh =
context.createMarshaller();
//Добавляем свойство форматированного вывода
marsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
//Выводим отображение объекта list на терминал marsh.marshal(list, System.out);
//Создаем объект вывода в файл: /home/upk/lab5.ListLetters.xml File file =
new File(System.getenv("HOME") + "/lab5.ListLetters.xml");
//Выводим отображение объекта list в файл
marsh.marshal(list, file);
}
}
Общая структура класса Test3 — полностью аналогична структуре класса Test1. Отличия состоят только в подготовке исходных данных для отображения и выделены на листинге серым фоном.
Третий тест представлен на рисунке 4.4, а студенту предлагается самостоятельно реализовать обратное отображение в классе Test4.
Рисунок 4.4 — Полностью аннотированное отображение класса ListLetters
187