5 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Пример работы с JAXB. Сохраняем Java объект в XML, восстанавливаем объект из XML

Содержание

dev64

Programming

Использование аннотаций с JAXB, генерация XML schema из java-кода

Галерея

Однажды, возникла необходимость настройки формата дат внутри XML документов. Работа с документами осуществлялась с помощью JAXB. Всвязи с этим коллеги нашли в интернете замечательную публикацию на сайте http://ooxs-be.goracer.nl/EN/java/Java%20and%20XML%20Binding.html

Ниже перевод не совсем близкий к тексту. Я слегка видоизменяю его для улучшения понимаемости. (По крайней мере мне хочется её улучшить). Если что-то не совсем понятно, смотрите оригинал.

Introduction

При работе с XML в Java, он может рассматриваться просто как текст, который должен быть прочитан изменен и куда-то записан. Т.о. это может быть сделано обычной конкатенацией строк или с помощью DOM-модели в памяти для доступа, создания или модификации документа.

В большинстве случаев, однако, кроме XML документа имеется набор классов — модель в виде beans или POJO, не важно как классы представлены и называются, но эти классы должны преобразовываться в XML документ и обратно из XML документа превращаться в набор классов. Это нужно для посылки этих классов в запросе на веб-сервис, для сохранения в файле и т.п.

Такая взаимосвязь модели Java объектов и XML представления документов называется англоговорящими программистами binding. Создание объектов из XML называется unmarshalling, а обратная операция генерации XML из Java объектов — marshalling.

Есть различные способы для реализации unmarshalling-а и marshalling-a:

  • Написать SAX парсер для создания Java объектов
  • Работать с DOM деревом для извлечения нужных объектов из него
  • Использовать специальный API такой как JAXB, Apache Commons Betwixt, и т.д.

Java Architecture for XML Binding (JAXB)

JAXB не только API. Существуют стандартные средства для генерации Java классов из XML schema (to form binding to XML), и для генерации XML schema из Java классов с расставленными аннотациями. Эти средства появились в Java как часть пакета JAXB.

Практический пример Java классов с JAXB аннотациями

Подходящий случай для использования JAXB — когда у вас имеется набор классов в приложении, которые вы хотите писать и читать в XML формате. Мы используем очень простой пример моделирования группы людей. У нас имеются два класса Group и People которые должны преобразовываться в XML и обратно. Дополнительно есть класс Application который и будет производить эти операции.

Преимущество JAXB в том, что в Java 6 мы используем стандартный API, ничего дополнительно не требуется устанавливать, конфигурировать и т.д.

Ниже корневой класс нашего XML документа, мы должны добавить аннотацию @XmlRootElement. propOrder = < «name», «members» >указывает в каком порядке элементы будут записываться в XML теги.

Подобным образом добавляем аннотации в дочерний класс

И, наконец, ниже класс Application выполняющий сериализацию (marshalling-unmarshalling) вышеприведенных классов с помощью JAXB:

Добавим код для генерации XML, и выполним приложение добавив в группу пару элементов для демонстрации JAXB API:

Благодаря аннотациям, лишь три строчки кода генерируют XML. (4 для лучшего форматирования для улучшения читаемости)

Однако в выходном XML есть ряд неожиданных элементов.
Каждый элемент Person помещён внутрь тега members вместо тега person. Это мы изменим позже. А пока посмотрим пример обратного преобразования. Сначала мы повторим предыдущий пример, создадим XML, потом запишем его в byte array. Затем сделаем unmarshalling из сгенерированного предварительно XML.

В результате теста дополнительно к XML получаем следующий output:

JAXB утилиты входят в стандартную инсталляцию Java. При установке Java 6 JDK они устанавливаются в каталог $JAVA_HOME/bin.
Например в дистрибутивах Linux подобных Ubuntu, они будут по умолчанию доступны для вызова из командной строки.

Генерация XML schema из Java-классов.

Чтобы JAXB утилиты стали доступны под Windows, нужно в переменных окружения указать путь к поддиректорию bin в каталоге с JDK. Для генерации XML schema из Java кода с добавленными аннотациями, используется утилита schemagen:

Допустим мы находимся в корневом директории исходников. Т.е. в нём у нас подкаталог be/ooxs/example/jaxb/ с исходниками:
Group.java, Person.java, Application.java

Тогда находясь в директории с исходниками мы генерируем XML схему такой командой (я тестируюсь под Windows):

  • -d . задает, что схема будет положена в текущий директорий
  • -cp . — classpath. Корневой директорий наших исходников. Т.к. мы в нём и находимся. То указываем точку.
  • третий параметр — путь к .java — файлу с исходным кодом корневого элемента нашего XML документа.

В итоге будет получен схема файл, который вы можете использовать по мере необходимости. Заметьте, что порядок элементов lastName, firstName, birthDate как определено в аннотациях.

Модифицируем аннотации

Для получения слегка улучшенной XML структуры, добавим несколько вещей:

Для начала добавим пару аннотаций, первая группирует все дочерние элементы используя дополнительный members элемент, вторая изменяет имя каждого дочернего элемента на person.

В результате при повторении теста получим XML:

Три подхода к сохранению XML

Сериализация, TrAX или привязка к данным: что выбрать для сохранения XML-документов?

Серия контента:

Этот контент является частью # из серии # статей: XML и Java

Этот контент является частью серии: XML и Java

Следите за выходом новых статей этой серии.

XML-данные надо где-то хранить

XML — замечательный формат представления данных, что подтверждается и наличием целого раздела, посвященного XML, на сайте IBM developerWorks. В наши дни обсуждение XML зачастую проходит в контексте Web-сервисов, преобразований Java™-объектов в XML и обратно, и даже использования баз данных XML вместо реляционных или объектно-ориентированных.

В то же время мало кого интересует, каким образом XML-документы, представленные в памяти с помощью DOM, JDOM или чего-то еще, преобразуются в файлы на диске, полные угловых скобок и кавычек. Честно говоря, запись XML в файл – это не самое захватывающее занятие, но от него никуда не деться. Вы только попробуйте представить себе ситуацию, при которой невозможно сохранить XML-документ в файл! Вы можете создавать XML-документы в памяти и пересылать их между различными модулями вашего приложения (а может даже между несколькими приложениями), будучи не в состоянии сохранить где-либо данные. Например, можно создавать документы для представления конфигураций, разработав всевозможные полезные утилиты для их чтения, при этом не имея возможности их сохранить. Или же можно прочитать сообщение SOAP, но нельзя записать его в файл в случае потери сетевого соединения.

Таким образом, важность записи файлов XML совершенно очевидна. Более того, если бы никого не волновали вопросы длительного сохранения данных, а единственное, что было бы нужно – это всего лишь преобразовывать их в памяти, то вполне возможно, что в XML просто не было бы необходимости, и уж во всяком случае, он не был бы настолько важен, как в наши дни.

При этом остается простой вопрос: а как лучше сохранять XML-данные в файл? Эта статья в основном рассчитана на программистов, которым приходится этим заниматься. При этом если вы вообще не сталкивались с такой необходимостью, то статья также будет полезна, т.к. вы научитесь это делать. Для тех же из вас, кто занимается сохранением данных, я решил рассмотреть три основных подхода:

  1. Использование DOM, JDOM API и им подобных технологий для записи в файл напрямую из структур данных XML в памяти.
  2. Использование TrAX (Transformation API for XML) и тождественного преобразования для сохранения XML-данных.
  3. Использование высокоуровнего API, такого как JAXB.

Сохранение непосредственно через API

Если чтение XML-данных осуществляется с помощью одного или нескольких API, то вполне логично и сохранять XML-документ, используя те же API. К примеру, при работе с XML через JDOM API после получения ссылки на объект JDOM Document запись можно осуществлять следующим образом:

Похожим образом можно записывать XML, используя новый API для загрузки и сохранения в спецификации DOM Level 3:

Новый DOM API можно использовать множеством различных способов. При этом какие-то из них сильнее привязаны к конкретной реализации DOM API, например, как вышеприведенный класс, который использует Xerces. Хотя есть и другие способы, не зависящие от конкретных библиотек, они не столь наглядны для демонстрации.

Преимущества

Преимуществом сохранения через API является то, что вы работаете напрямую с API и, следовательно, держите все под контролем. Например, вы можете добавлять новые строки, указывать отступы и т.д., вплоть до мельчайших деталей. При этом мало, что отделяет вас от непосредственного доступа к файлу: нет ни оберток API, ни каких либо абстрактных слоев, так что вы можете работать с XML на очень низком уровне. Так что если вы уверенно владеете JDOM или DOM, то использование этих API – очень удобный способ сохранения XML-данных.

Читать еще:  Rcgamebox что это за программа?

Недостатки

Недостатки прямого сохранения через API зачастую являются обратной стороной преимуществ. Из-за того, что практически все аспекты вывода находятся под контролем программиста, неправильное использование API легко может привести к неверному сохранению данных. Например, распространенными ошибками являются неправильные переводы строк, неверная кодировка, а также ошибки ввода-вывода. При этом приходится работать на очень низком уровне, практически без помощи каких либо вспомогательных утилит (JDOM предоставляет только методы Format.getPrettyFormat() и Format.getCompactFormat() , а DOM – и того меньше). Таким образом, необходимо досконально знать кодировки, форматы записи, правила отступов и остальные аспекты, имеющие какое либо значение для сохранения файла.

Форматы преобразования

Одна из популярных альтернатив – это использование TrAX и тождественного преобразования. TrAX – это API для XML-преобразований (Transformation API for XML). В настоящее время TrAX является частью JAXP, которая включаются практически во все релизы Java (кроме Micro Edition). TrAX позволяет использовать таблицы стилей XSL для преобразования XML-документов. TrAX предоставляет возможность преобразования SAX-событий или DOM-документов в XML-файлы и обратно, что удобно, т.к. SAX и DOM являются наиболее распространенными методами работы с XML. Например, можно взять DOM-документ, преобразовать его с помощью TrAX и сохранить результат в файле. Или же можно считать файл, преобразовать его и представить в виде DOM Document .

В частном случае можно использовать таблицу стилей, не задающую никакого преобразования данных, и использовать ее для перевода документа из одного формата в другой. Использование такой таблицы стилей, которая просто дублирует входной документ, называется тождественным преобразованием. Таким образом, можно считать документ из файла, применить тождественное преобразование и получить тот же самый документ в виде DOM. Обратное действие—из DOM в файл—является ничем иным, как сохранением XML. Это делается примерно так:

В этом примере DOM-документ сохраняется в XML-файле outputFile.xml.

Преимущества TrAX

Наибольшим плюсом TrAX является простота использования. TrAX легко вызывается из Java-кода и не требует серьезных знаний SAX или DOM, что делает его очень привлекательным для программистов, не обладающих уверенными навыками работы с XML. Вдобавок, его могут использовать начинающие программисты, незнакомые с SAX или DOM, т.к. достаточно выучить 10-20 строк кода и можно сохранять XML-данные в файл или преобразовывать в DOM-документы и наборы SAX-событий.

Обратная сторона использования TrAX

Наибольшим недостатком TrAX является то, что при всей простоте преобразований, достаточно трудно контролировать мелкие детали вывода, такие как переводы строк, кодировки, пробелы и отступы. TrAX поддерживает работу с этими аспектами сохранения, но это далеко не так просто, как в случае непосредственного использования DOM или JDOM. Как правило, простота использования TrAX сочетается с недостатком гибкости при сохранении в файл, по крайней мере, на первый взгляд.

При этом, практически всего, что можно делать через DOM или JDOM, можно достичь и при использовании TrAX, но это не настолько просто и интуитивно. Приходится вникать в детали XSLT и TrAX API, которые имеют весьма слабое отношение к практическим задачам сохранения XML.

Использования привязки к данным (data binding) для сохранения XML

Еще одним способом перевода XML в статическое представление—особенно, если это представление должно быть в виде файла на диске—является использование API для привязки к данным (data binding), таких как JAXB. Несмотря на то, что привязка к данным, как правило, не рассматривается в качестве метода их сохранения, она фактически является таковым. Это не что иное, как способ взять XML-документ в памяти и записать его в файл.

К сожалению, ввиду ограниченности объема статьи, я не могу подробно рассказать, что такое привязка к данным, но вы можете прочитать несколько статей на эту тему на сайте developerWorks. Ниже представлен фрагмент кода в стиле JAXB, который сохраняет XML на диск:

Вы можете задавать различные параметры, такие как кодировка выходного файла через объект Marshaller . В смысле гибкости настройки параметров вывода, JAXB не сильно отличается от вышерассмотренных подходов.

Преимущества JAXB

Одним из наиболее существенных преимуществ JAXB является простота использования, особенно при решении несложных задач. К тому же, в то время как SAX и DOM считаются достаточно сложными в использовании (по крайней мере, в кругу рядовых программистов), понимание JAXB необходимо практически каждому Java-разработчику. Как следствие, выложено много статей и руководств по JAXB, что подтверждается обзорами публикаций на сайтах типа developerWork за 2007 год. Кроме этого, JAXB лучше поддерживается, чем DOM или SAX. Несмотря на то, что реализации SAX и DOM также включены в релизы Java-платформы, JAXB является детищем Sun Microsystems, так что его поддержка обещает быть лучше.

От вас не требуется глубоких знаний XML, чтобы начать использовать JAXB. Вы можете работать с обыкновенными Java-объектами (а не специфическими интерфейсами, типа Node или Text в DOM), а затем сохранить их в XML. Как следствие, вам не придется изучать гору нового материала, перед тем как начать работать с JAXB, что особенно ценно, когда ваш босс требует от вас результатов немедленно.

Недостатки JAXB

В то же время необязательность знания XML также является определенным недостатком JAXB, потому как чем меньше вы знаете об XML, тем сложнее разумно использовать JAXB. В итоге, может запросто получиться плохо отформатированный XML-документ или документ, в котором присутствует только часть объектов, а, может, и вовсе не те объекты, которые должны были быть сохранены.

В результате разработчики зачастую вынуждены либо вообще отказаться от использования JAXB, либо начинать глубже изучать XML, SAX и DOM. Более того, после этого многие из них просто переходят на использование SAX и DOM, оставляя для JAXB лишь простейшую функцию конвертации между XML и Java-объектами.

И последний подход.

Я сознательно обошел вниманием еще один вариант формирования XML-файла, а именно: запись последовательности бит, байт и строк непосредственно в FileOutputStream или FileWriter . Это вполне осуществимо на практике и иногда используется. Однако в этом случае вместо сохранения XML-данных происходит просто создание нового XML-документа на основе данных, представленных в каком-либо другом формате. Подобные действия легко распознать на практике, потому как код, как правило, выглядит как на фрагменте ниже:

В таком подходе нет ничего фундаментально неверного, просто вместо сохранения XML-документа, происходит сохранение данных и одновременное наполнение ими XML-файла. Таким образом, вопросы сохранения именно XML-документов в данном случае оказываются несущественными, т.к. невозможно отделить сохранение данных от перевода их в XML.

Заключение

В целом не существует единственно верного подхода к сохранению XML-документов, так что полезно обсуждать различные варианты, используемые разными Java и XML-разработчиками. Главное, спросите себя, является ли ваш подход к этой общей проблеме последовательным? Позволяет ли он сохранять XML-документы на диске в виде, удобном для последующего использования: чтения, понимания и обмена данными между приложениями?

Таким образом, целью этой статьи было заставить людей больше общаться на тему применимости конкретных подходов в тех или иных ситуациях. Опыт других разработчиков может оказаться очень полезным при решении вашей проблемы, так что не пожалейте времени на изучение форумов по Java и XML на сайте developerWorks (см. Ресурсы), а также сообщите нам, как вы решаете задачу сохранения XML. Если ваш выбор обусловлен необходимостью поддержки некой специальной функциональности, расскажите заодно и о ней. До встречи в online!

Пример работы с JAXB. Сохраняем Java объект в XML, восстанавливаем объект из XML

Я поначалу совсем не хотел останавливаться на том, что такое XML, но все-таки несколько слов сказать придется, чтобы те, кто про него услышали первый раз, прочитав эти строки, были в курсе основных идей.
По сути XML представляет собой обычный текст, который разделяется на логические группы с помощью специальных меток, которые называют “тэг”.
Тэг представляет собой слово, которое заключено в угловые скобки — например вот так:

Для того, чтобы начать группу вы указывает просто слово в скобках — еще раз повторим
Для окончание группы вы указываете такой же тэг, но слово предваряется символом “/”. Вот так:

В итоге группа внутри тэга test выглядит вот так:
Группа символов для тестирования

Тэги могу вкладываться один в другой — например вот так:

Группа символов для тестирования 01
Группа символов для тестирования 02
Группа символов для тестирования 03

Кроме вложений текста в тэгах можно указывать атрибуты — вот так:

Группа символов для тестирования 01

Назначение тэгов очень простое — надо отметить/выделить/сгруппировать какую-то информацию для того, чтобы потом ее можно было использовать. Это может быть список имен, список книг, список фирм, список вакансий и т.д.
Например, я хочу написать список контактов, с указанием имени, фамилии и e-mail. Можно сделать это так (но можно и по-другому — здесь все зависит от вашей фантазии и требований задачи):

Василий
Курочкин
vas@pisem.net

Георгий
Папанов
geogr@gmail.com

Семен
Баринов
barinov@yandex.ru

Не ищите тайного смысла — я просто сделал строку, в которой выделил нужные мне части — контакт (тэг contact) и внутри определил имя, фамилию и e-mail (тэги firstName, lastName, email). Также с помощью атрибута type я определи тип контакта — друг, коллега, однокурсник. Теперь просматривая строку я могу выделить нужные мне части информации. Это удобно и ничего более. Причем здесь больше удобства даже не для визуального восприятия (это спорно), а для программной обработки — достаточно несложно написать программу, которая найдет конкретные кусочки.

Читать еще:  Avast представила защищенный браузер Avast Secure Browser - CNews

Теперь новичкам надо посмотреть какой-нибудь XML, чтобы увидеть больше примеров и убедиться, что в главном я прав (хотя все в мире относительно).

Работа с XML

В первую очередь я хотел бы высказать свою позицию по поводу самого XML и уже на основе этого продолжать повествование.
Для меня XML — очень мощная технология, которая позволяет хранить, передавать и обрабатывать сложноструктурированные данные. Т.е. если я хочу иметь: список фирм с их телефонами и счетами, каталог книг с авторами и отзывами, описание структуры страниц сайта с комментариями, состояние всех автобусов в городе с их координатами, водителями, номерами и прочая — все это может быть удобно сохранено в виде XML и, что крайне важно и удобно, может быть передано в любую систему, которая написана на любой платформе — на .NET, PHP, Object C, Delphi, C++.
Проведите мысленный эксперимент — попробуйте написать строку, в которой передать информацию о своих контактах (где у одной персоны может быть несколько телефонов, e-mail, любимые книги, места работы, места учебы и … да хватит пока). Что важно — это должна быть обычная строка (несколько строк), которая позволяет разбирать эту информацию в ту структуру, которую я описал — класс Java. Там надо предусмотреть какие-то разделители, информацию об именах полей (группах полей). Попробуйте — и вы придете к чему-то подобному XML.

Также я вам советую очень серьезно подойти к изучение самого XML, т.к. на сегодня эта технология используется в очень широком спектре всевозможных пакетов, библиотек, платформ и вам никуда от нее не скрыться.

Итак, после всего вышесказанного мы видим, что нам приходит строковое представление чего-то важного в какой-то определенной структуре, которая требует наличия достаточно важных функций — нам же надо как-то работать с этой информацией. Не лежать же ей мертвым грузом. Функции достаточно очевидны:

  1. Разбор. Надо уметь разобрать строку на что-то более удобное для обработки — пытаться вставить внутрь строки или находить какое-то поле определенной записи из строки — это достаточно неудобно. Значит нам надо иметь некоторый набор классов для представления нашей строки в виде структуры объектов.
  2. Поиск. По структуре данных надо уметь что-то искать. Причем не подстроку, а какую-то группу полей, которые относятся к определенному объекту — например полная информация о книге — наименование, авторы, отзывы. Или список контактов с фамилией “Сидоров”.
  3. Проверка. Данные должны быть корректными, т.е. там должны быть только определенные поля, с определенным наполнением и они должны быть правильно скомпанованы в нашей строке.
  4. Преобразование. Хоть XML достаточно удобно описывает структурированные данные, это не значит, что его удобно просматривать обычному человеку или всегда удобно обрабатывать. Нередко для решения этого вопроса требуется преобразовать XML в какое-либо другое текстовое представление — например в тот же HTML (который является частным воплощением XML). Или даже в обычный текст.

В общем-то это все, что на мой взгляд наиболее важно. Нам надо уметь работать с информацией, которая записана в формате XML. Приступим к рассмотрению каждого пункта.

Разбор — Parsing

В слэнге программистов часто используется слова “парсинг”, который и обозначает разбор строки (или еще чего-нибудь) в какую-то структуру. Здесь надо выделить два момента:

  1. Разбор строки определенным алгоритмом
  2. Сохранение результатов разбора в какую-то структуру вместо строки — ибо со строкой многие операции делать просто неудобно.

Что касается второго пункта, то на сегодня существует по сути одна унифицированная структура, которая называется Document Object Model (DOM).
DOM представляет собой набор интерфейсов (и их реализаций), которые являются специализированными объектами для хранения “узлов” (node) XML-документа. По сути каждый тэг — это “узел” (нода — я буду использовать этот термин, т.к. очень привык). Информация внутри тэга — тоже нода. По сути любой разобранный XML — это набор элементов типа Node и еще более специализированных, построенных в дерево.
Почему дерево ? Да потому что у каждой ноды может быть список дочерних нод и у каждой из них тоже может быть “детки”. Так и строится дерево. Если вам сложно это увидеть, то советую посмотреть какую-либо классическую книгу по алгоритмам и структурам данных — можно старого доброго Никлауса Вирта «Алгоритмы и структуры данных». Книгу можно найти в интернете, ну или купить.

Давайте рассмотрим загрузку файла и редактирование построенного дерева на примере. Наша программа считывает XML-файл со списком книг и печатает их свойства. Сам XML-файл выглядит вот так:

Использование Java JAXB на примерах

В этом уроке покажу как использовать библиотеку JAXB для работы с XML. На примерах рассмотрим как объекты Java записываются в файлы XML, а данные XML считываются в объекты.

Java Architecture for XML Binding (JAXB) — это программная структура, которая позволяет разработчикам отображать классы Java в представления XML. JAXB позволяет делать сохранение объекта в файл и обратно в объекты.

В Java 9 JAXB переместился в отдельный модуль java.xml. В Java 9 и Java 10 нам нужно использовать параметр —add-modules = java.xml.bind. В Java 11 JAXB был удален из JDK, и нам нужно добавить его в проект в виде отдельной библиотеки через Maven или Gradle.

В наших примерах мы используем JDK 11 и Maven для создания наших приложений.

Определение JAXB — что это?

Маршалинг — это процесс преобразования объектов Java в документы XML. Unmarshalling — это процесс чтения документов XML в объекты Java. Класс JAXBContext обеспечивает точку входа клиента в API JAXB. Он предоставляет API для маршалинга, демаршалинга(unmarshal) и проверки.

Следующий файл POM содержит необходимые JAR JAXB настройки.

В дополнение к включению зависимостей JAXB мы используем плагин maven-assembly-plugin, чтобы упаковать все зависимости в один JAR-файл.

Пример использования JAXB для записи XML

В первом примере мы записываем объекты Java в файл XML.

Этот bean-компонент будет преобразован в определенный тег XML.

С помощью аннотации @XmlRootElement мы определяем имя тега XML.

С помощью атрибута propOrder @ XmlType мы определяем порядок подэлементов.

@XmlElement(name = «title»)
public String getName() <
return name;
>

Мы можем изменить имя элемента по умолчанию на заголовок.

BookStore — это класс, который содержит список, в который мы помещаем наши объекты книги.

@XmlRootElement(namespace = «com.zetcode»)
public class BookStore <
Мы определяем корневой элемент с помощью аннотации @XmlRootElement.

// XmLElementWrapper генерирует элемент-оболочку вокруг представления XML
@XmlElementWrapper(name = «bookList»)
// XmlElement устанавливает имя
@XmlElement(name = «book»)
private ArrayList bookList;

Аннотация @XmlElementWrapper определяет элемент-обертку вокруг элементов книги. Аннотация @XmlElement определяет имя элемента XML, который находится внутри оболочки.

Пример чтения XML JAXB (unmarshal)

Во втором примере мы считываем данные обратно в объекты Java.

Средняя оценка / 5. Количество голосов:

Спасибо, помогите другим — напишите комментарий, добавьте информации к статье.

Или поделись статьей

Видим, что вы не нашли ответ на свой вопрос.

Архитектура Java для привязки XML (JAXB) | Set-1

Архитектура Java для привязки XML (JAXB) определяет API для чтения и записи объектов Java в и из документов XML. JAXB дает разработчикам Java эффективный и стандартный способ отображения между XML и кодом Java. JAXB облегчает разработчикам расширение своих приложений с помощью технологий XML и веб-сервисов. Сначала JAXB разрабатывался как отдельный проект, но в конце концов стал частью JDK в Java 6.

Архитектура Java для функций связывания XML

Применение JAXB

JAXB Framework полезен для выполнения следующих операций:

  • Измените содержимое XML в представление Java.
  • Доступ и обновление представления Java
  • Измените представление Java на контент XML.

JAXB Аннотации

JAXB использует аннотации для обозначения центральных элементов. Некоторые Основы JAXB Аннотации, которые могут использоваться в вашем Java-классе для операций JAXB:

Две основные концепции, связанные с JAXB:

  1. Marshalling: конвертировать Java-объект в XML
  2. UnMarshalling: конвертировать XML в Java-объект

сортировочный

Ниже приведен пошаговый алгоритм для преобразования Java-объектов в XML (Marshalling):

  1. Сначала создайте объекты Java для маршаллинга.
  2. Создайте объект JAXBContext и инициализируйте объект Marshaller.
  3. Чтобы получить форматированный вывод XML, можно установить для JAXB_FORMATTTED_OUTPUT значение True (этот шаг не является обязательным).
  4. Создайте объект файла xml, указав расположение файла в качестве параметра для класса файлов
  5. Вызвать метод маршала для объекта Marshaller и передать созданный объект XML-файла методу маршала.
  6. Теперь файл XMl создан.

Пример : сначала давайте создадим объект Student с атрибутами FullName, StudentDegree, StudentMarks, затем мы собираемся преобразовать этот объект в XML-схему, выполнив следующие шаги.

Создание класса Student.java с атрибутами FullName, StudentDegree, StudentMarks.

// Ниже аннотация определяет корневой элемент файла XML
@XmlRootElement

public class Student <

private String FullName;

private String StudentDegree;

private String StudentMarks;

public String getFullName()

// Устанавливает элемент xml с именем элемента «Student Name»

@XmlElement (name = «Student Name» )

public void setFullName(String fullName)

public String getStudentDegree()

@XmlElement (name = «Student Degree» )

public void setStudentDegree(String studentDegree)

public String getStudentMarks()

@XmlElement (name = «Student Marks» )

public void setStudentMarks(String studentMarks)

Основной класс: JAVAObjToXml.java, который собирается преобразовать объект Student в XML-схему.

public class JAVAObjToXml <

public static void main(String[] args)

// создание объекта Student

Student student = new Student();

student.setFullName( «Aman Singh» );

// Создать контекст JAXB и инициализировать Marshaller

JAXBContext context = JAXBContext.newInstance(Student. class );

Marshaller marshaller = context.createMarshaller();

// Для форматированного вывода xml

// Создать объект файла xml

File XMLfile = new File( «D:\StudentRecord.xml» );

// Объект Java в файл XML

// Печать на консоль

catch (JAXBException e) <

Выход :

generated StudentRecord.xml File for Student Object.

Плюсы и минусы использования JAXB

Плюсы:

  • Легко упорядочить XML-файл для других целей данных, таких как inputStream, узел DOM.
  • Легко демонтировать файл XML из других целей данных.
  • Не нужно знать о методах синтаксического анализа XML.
  • проще в использовании, чем DOM или SAX парсер
Читать еще:  Victoria privileged instruction что делать?

Минусы:

  • JAXB — это высокоуровневый API, поэтому он меньше контролирует синтаксический анализ, чем SAX или DOM.
  • Это медленнее, чем SAX.

Применение JAXB для XML-сериализации объектной модели с иерархией наследования. 6 min read

В мире Java библиотека JAXB уже давно (как сообщает нам wikipedia с 2006 года) и по праву является распространенным и очень удобным инструментом для XML-cериализации объектов и даже объектных моделей. В интернете есть масса примеров и целые сторонние библиотеки, построенные на JAXB — взять хотя бы docx4j (http://www.docx4java.org/trac/docx4j), которая работает с моделью документа в Open-XML формате. Так же много информации можно почерпнуть у самих авторов JAXB — https://jaxb.java.net/. Без труда найдутся в интернете прекрасные готовые исходники для генерации классов Java по XML-модели. Примеров масса и можно увлекательно провести время, изучая возможности JAXB.

Но практически все примеры приводятся для одного простого класса, который сериализуют в XML, что называется, с нуля. А что делать, если уже есть некая готовая объектная модель со сложной структурой наследования и зависимостей, которые запрещены к изменениям? Где следует применить JAXB-аннотации? Куда их добавить — непосредственно в каждый из доброй полторы сотни классов, либо в один базовый? Если в каждый класс иерархии, то целесообразна ли такая переделка с точки зрения объема выполненной работы? Если в один-два базовых, то будет ли вообще работать XML-сериализация? Да, действительно много вопросов, и посмотрим, как JAXB с этим справляется для конкретной задачи проекта.

Например, есть модель документа: Root – некий корневой элемент, контейнер для других элементов. Он может содержать Paragraph, который также является контейнером для элементов Text. В свою очередь все элементы являются контейнерами атрибутов, например у Paragraph это Alignment и Indent, у Text – Bold, Italic, FontName, FontSize и Color. Конечно, это неполный перечень, но в качестве примера достаточный. Кроме того, условием для контейнеров элементов – Root и Paragraph, является то, что они могут содержать неограниченное количество подэлементов, т.е. Root содержит много Paragraph, а Paragraph — много Text. Но контейнеры атрибутов могут содержать каждый атрибут в единственном экземпляре. Например, зачем элементу Text несколько FontName или Bold?
Таким образом, есть уже готовая модель элементов и атрибутов, со своей специфической бизнес-логикой, полями, методами и т.д.

Это все, хотя реальная модель содержит гораздо больше элементов, атрибутов, ограничения по содержимому: например, Root может содержать только Paragraph, в свою очередь Paragraph – только Text, Text – только текстовые атрибуты, Paragraph – свои, Root – свои. Сейчас же в этом примере можно сделать все, что угодно и заполнить модель ошибочными данными, но речь тут о JAXB, поэтому перейдем уже к XML-cериализации этой модели, ее трудностям и их решениям.
Чтобы создать тестовую модель в памяти воспользуемся методом-стартером main(), например в RootElement:

Вот теперь хотелось бы иметь возможность сохранить эту структуру в XML-файл и зачитать обратно. Причем надо это сделать так, чтобы не были затронуты уже используемые в бизнес-логике механизмы – т.е. готовые поля и методы должны остаться нетронутыми, и мы применим JAXB только чтобы незаметно для внешнего мира расширить возможности модели сохранять/читать себя в/из XML-файла.

JAXB работает через аннотации: @XmlElement, @XmlType и т.д. Классы с такими аннотациями через механизм рефлекшена проходят так называемый маппинг, и происходит магия связывания объекта и его полей с XML.

Начнем с того, что корневой элемент надо обозначить аннотацией @XmlRootElement.

В данном случае, очевидно, что это сам RootElement:

Атрибут name используется для того, чтобы определить, как будет назван элемент в XML-файле.
Добавим в абстрактный атрибут специальные методы:

Название метода getXmlValue не играет роли, главное, что мы делаем его protected и он невидим извне и не влияет на существующую бизнес-логику, а @XmlElement сообщает JAXB, что в XML у атрибута должен быть элемент с именем name = «Value», в котором будет value атрибута. Причем для JAXB важно иметь пару getter-setter, чтобы он мог сохранять/читать XML.

Да, конечно, можно сделать проще и без getter-setter – повесить @XmlElement прямо на value атрибута:

Но мы договорились не трогать содержимое модели, а ее просто чуть-чуть и незаметно расширить.
Это все? Нет! Сам класс абстрактного атрибута нужно обозначить так:

@XmlAccessorType(XmlAccessType.NONE) позволит избежать маппинга по умолчанию, когда все найденные поля, пары getter-setter и т.д. будут принудительно пытаться записаться в XML.
@XmlTransient позволит в свою очередь избежать так называемой коллизии имен. Возникает такая коллизия из-за value – это и поле класса, и элемент в XML @XmlElement(name = «Value»), причем для JAXB регистр не имеет значения – value и Value одинаковы в XML. Чтобы точно сказать JAXB, что за Value пойдет в XML, мы и используем комбинацию @XmlAccessorType(XmlAccessType.NONE) и @XmlTransient – таким образом класс «закрывается» от JAXB, и открывает только getter-setter через @XmlElement(name = «Value»).
Конечно, напрашивается подозрения в искусственности проблемы – что мешает назвать @XmlElement(name = «MySuperPuperValue») и избежать @XmlTransient? Да ничто, просто мне приятнее видеть в XML «Value».
Идем дальше – что нам надо теперь сделать с атрибутами-наследниками? Да практически ничего! Атрибуты, у которых value – простые типы (boolean, int …) или String не требуют вообще никаких доработок. JAXB сериализует их в XML автоматически. Это не может не радовать, т.к. таких атрибутов в реальной модели действительно очень много и подобная полная переработка вызвала бы сомнения в целесообразности затрат.
В данном случае оставим без изменений BoldAttribute, ItalicAttribute, FontName и FontSize у текста, и IndentAttribute у параграфа.
А что с ColorAttribute? Вот он как раз не простой тип, а java.awt.Color, поэтому требует конвертации в некий простой. Для этого JAXB предлагает абстракцию XmlAdapter. Приведу тут простую реализацию:

Что делает этот адаптер? Получает java.awt.Color и преобразует его в число из его RGB значения.
Переопределим в ColorAttribute @XmlElement:

Теперь JAXB сможет сохранить java.awt.Color.RED из примера в main() так:
-65536.
Да, есть еще замечание по java.awt.Color – в реальной модели я использовал другой адаптер, т.к. color.getRGB() теряет alpha-составляющую цвета и пришлось хранить цвет в XML в специальной строке RGBA:

При использовании этого адаптера в XML мы увидим следующее:
rgba(255,0,0,255)
Идем дальше – почему AlignmentAttribute нужно доработать?
У него value – Enum, а это тоже не простой тип, хотя вроде бы должно быть наоборот – номер и все тут. Но JAXB нужно научить работать с ним. Есть два способа – либо написать адаптер, аналогично Color, либо применить аннотации. Я принял второе решение. Объявляем enum как тип в определенном namespace:

Это нужно для того, что если у нас много разных атрибутов, у которых enum называется одинаково – VALUE, как в имеющейся модели, и JAXB не поймет кто чей.
Переопределим у AlignmentAttribute @XmlElement:

По атрибутам все. Теперь мы имеем представление, как доработать остальные для JAXB – атрибуты с простыми типами value остаются без изменений, enum-атрибуты – нуждаются в namespace типа, а атрибуты сложных типов нуждаются в адаптерах.
Переходим к элементам.
Аннотируем класс TerminalElement через @XmlAccessorType(XmlAccessType.NONE) – как уже описывалось выше, чтобы исключить ненужный маппинг всех полей и методов по умолчанию. Вот BranchElement, благодаря этому, уже не нуждается в такой аннотации — она есть в супер-классе TerminalElement, и этого достаточно.
Да, еще одним важным условием для XML-cериализации является наличие конструктора без параметров, поэтому BranchElement как раз содержит такой пустой конструктор.
Далее интереснее – добавим в TextElement следующее:

Это значит, что в XML будет элемент с именем «Text», содержащий текст TextElement – все просто:
test.
Для эксперимента вместо элемента можно использовать атрибут:

И в XML мы увидим:

А что с атрибутами? JAXB может сериализовать автоматически не только простые типы и String, но и простые наборы данных типа массив и List, где T – любой тип поддерживающий XML-сериализацию, т.е. подготовленный для JAXB.
Что делать с нашей LinkedHashMap из TerminalElement? Правильно – писать адаптер, например AttributeListAdapter:

Адаптер умеет передавать элементы из Map в виде простого списка элементов в JAXB, и наоборот принимать элементы из простого списка JAXB и записывать их в Map – все просто.
А в TextElement теперь нужно сделать оболочку (wrapper) для списка атрибутов:

Т.е. мы указываем, что в XML список будет находиться в элементе с именем «Attributes», а каждый встреченный атрибут так же получает определенное имя: BoldAttribute – Bold, FontNameAttribute – FontName и т.д.
Аналогично описываем атрибуты ParagraphElement:

И последнее – нужна оболочка (wrapper) для списка элементов для элемента-контейнера. Например, для ParagraphElement:

В XML список подэлементов будет в элементе с именем «Elements».
Т.к. elements уже простой список List , то писать адаптер не нужно – JAXB справится с ним автоматически.
Для RootElement аналогично:

Теперь осталось написать методы сохранения/загрузки модели в/из XML-файла, добавим их прямо в тест в main():
Сохранение в XML-файл:

Загрузка из XML-файла:

Модель из примера в XML-файле будет выглядеть так:

Файл прекрасно зачитывается обратно в модель.
Наша цель достигнута – мы можем сохранять текущее состояние документа в XML-файл и загружать его впоследствии обратно, нам не пришлось делать полную переделку модели, все незначительные изменения находятся в базовых абстрактных классах, благодаря protected являются скрытыми извне, мы полностью контролируем и можем легко менять именование и структуру элементов в XML-файле.

Ссылка на основную публикацию
Статьи c упоминанием слов:
Adblock
detector