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

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