Теперь данные в файлах XML имеют тенденцию быть иерархическими по своей природе. Например, рассмотрим этот XML-файл:
|
1
2
3
4
5
6
7
8
9
|
<?xml version="1.0" encoding="UTF-8"?><person> <firstname>Barok</firstname> <lastname>Obama</lastname> <age>52</age> <car> <model>Green Ford Focus 1.4L</model> </car></person> |
В этом случае у человека Барока Обамы есть автомобиль, который является Зеленым Фордом Фокусом. Здесь мы видим иерархические характеристики XML. Автомобиль под Лицом. В более изощренном примере у Человека может быть Автомобиль, у которого есть Автомобильное радио, с Усилителем, у которого есть Транзисторы и т. Д. Но давайте сейчас остановимся на нашем более простом случае. Предположим, мы хотим удалить этот XML-файл с помощью JAXB. Нам нужны все данные человека (имя, фамилия и т. Д.) И модель автомобиля, принадлежащего этому человеку. Мы создаем POJO Person и Car POJO и комментируем соответствующим образом.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
@XmlRootElement@XmlAccessorType(XmlAccessType.FIELD)@XmlType(propOrder={"name", "firstname", "lastname"})public class Person { private String firstname; private String lastname; private int age; private Car car; public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFirstname() { return firstname; } public void setFirstname(String name) { this.firstname = name; } public Car getCar() { return car; } public void setCar(Car car){ this.car= car; }} |
|
01
02
03
04
05
06
07
08
09
10
11
|
public class Car { private String model; public String getModel() { return model; } public void setModel(String model){ this.model = model; }} |
Чтобы разобраться в этом, мы просто делаем
|
1
2
3
4
5
6
|
public static void unmarshall() throws Exception { JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); Person person = (Person)unmarshaller.unmarshal(new File("Person.xml")); System.out.println("Perosn is=" +person.toString());} |
Все это кажется очень простым — особенно если учесть, что сущность Car даже не нуждается в каких-либо аннотациях! Однако, у Car есть только один атрибут, и может показаться излишним иметь класс POJO для чего-то, от чего мы хотим только один атрибут! Помните, что это простой пример, представьте, если иерархическая структура была намного глубже. Что-то вроде внешней сущности, содержащей сущность, которая содержала другую сущность, которая содержала даже другую сущность, и все, что мы хотели, — это внешняя сущность и один атрибут от самой глубокой вложенной сущности. По сути, это та же проблема, но просто еще более излишняя. Мы должны были бы обеспечить наличие класса POJO для всего в иерархии — даже для сущностей, от которых мы ничего не хотели. Никто не любит раздувать код. Так что мы можем сделать?
Ну, первое, что мы должны помнить, это то, что JAXB — это спецификация, для которой есть много реализаций (например, JaxMeAPI, MOXy, Metro). Если бы мы использовали эталонную реализацию JAXB (поставляется с JDK, мы мало что можем сделать). У нас должен быть автомобиль и человек POJO. Однако, если мы используем реализацию MOXy из EclipseLink, мы можем использовать некоторые из ее расширений, чтобы помочь нам. Более конкретно, мы можем использовать расширение MOXy @XmlPath, которое вдохновлено XPath.
Давайте посмотрим на это в действии. Вот обновленный человек POJO.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
@XmlRootElement@XmlAccessorType(XmlAccessType.FIELD)@XmlType(propOrder={"name", "firstname", "lastname"})public class Person { private String firstname; private String lastname; private int age; public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFirstname() { return firstname; } public void setFirstname(String name) { this.firstname = name; } @XmlPath("car/model/text()") private String model; public String getModel() { return model; }} |
Так куда же девался автомобиль POJO? Ну, это удалено. Нам это больше не нужно. Пока-пока.
Используя аннотацию MOXy @XmlPath, нам не нужен автомобильный POJO. Эта аннотация находится в пакете org.eclipse.persistence.oxm.annotations, и получить ее в вашем classpath действительно просто. Если вы пользователь maven, просто добавьте:
|
1
2
3
4
5
|
<dependency> <groupid>org.eclipse.persistence</groupId> <artifactid>eclipselink</artifactId> <version>2.3.2</version></dependency> |
Чтобы указать вашему JDK использовать MOXy для реализации JAXB во время выполнения, вы помещаете файл с именем
jaxb.properties в том же каталоге, что и ваши JAXB POJO. Он содержит одну строку:
|
1
|
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory |
Чтобы убедиться, что вы используете реализацию MOXy, просто проверьте контекст JAXB:
|
1
2
|
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);System.out.println("jaxbContext is=" +jaxbContext.toString()); |
Вы должны увидеть что-то вроде:
|
1
|
jaxbContext is=org.eclipse.persistence.jaxb.JAXBContext@5e3974 |
После этого нет никаких изменений. Можно использовать точно такой же код демаршаллинга.
Одна из причин, почему мне действительно нравится это расширение, заключается в том, что оно означает меньше кода. Обычно это означает более чистый код и более понятный код. Это становится еще более очевидным в более сложных сценариях, где сущности намного глубже в иерархической структуре, чем этот простой пример. Неважно, если вы используете что-то вроде XJC для генерации ваших POJO, у вас все еще есть раздувание кода.
Помните, что JAXB намеревался быть более чистой моделью программирования, чем альтернативы JAXP, такие как SAX и DOM, но в сценариях с глубокими иерархиями профилирование классов с использованием JAXB не делает его более чистым. Помните, было бы довольно легко игнорировать классы, которые вы не хотите использовать, используя DOM и XPath или даже просто используя SAX.
MOXy возвращает борьбу за чистоту обратно в JAXB, предоставляя возможность использовать выражения XPath для чего угодно в нашем XML-файле.
Примечание: MOXy только что был включен в качестве реализации JAXB для WebLogic 12c .
Рекомендации:
- МОКСИ страница проекта
- Блог Блеза Дафана
- Сделайте свой JAXB чище с помощью MOXy от нашего партнера JCG Алекса Стейвли в техническом блоге Дублина
Статьи по Теме :