現在,XML文件中的數據本質上趨于分層。 例如,考慮以下XML文件:
<?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>
在這種情況下,Barok Obama人擁有的汽車是Green Ford Focus。 在這里,我們看到了XML的層次結構特征。 車在人下。 在一個更復雜的示例中,一個人可以擁有一個汽車,該汽車具有一個汽車收音機,該汽車具有一個放大器,該汽車具有晶體管等。但是,讓我們暫時堅持我們的簡單情況。 假設我們要使用JAXB解組該XML文件。 我們需要所有人的詳細信息(名字,姓氏等)以及屬于該人的汽車的型號。 我們創建一個Person POJO和一個Car POJO并進行適當的注釋。
@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;}
}
public class Car {private String model;public String getModel() {return model;}public void setModel(String model){this.model = model;}
}
要解組,我們只需做
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類似乎有點過頭了! 記住,這是一個簡單的示例,想象一下層次結構是否更深。 類似于包含實體的外部實體,其中包含另一個實體,該實體甚至包含另一個實體,而我們所需的只是外部實體和來自最深層嵌套實體的一個屬性。 本質上是相同的問題,但更多的是矯kill過正。 我們必須確保層次結構中的所有內容都有POJO類,甚至對于我們一無所求的實體也是如此。 沒有人喜歡代碼膨脹。 所以,我們能做些什么?
我們首先要記住的是,JAXB是一個規范,該規范有許多實現(例如JaxMeAPI,MOXy,Metro)。 如果我們要使用JAXB參考實現(隨JDK一起提供,則無能為力)。 我們必須有一個汽車和人POJO。 但是,如果我們使用EclipseLink的MOXy實現,則可以使用其一些擴展來幫助我們。 更具體地說,我們可以使用受XPath啟發的MOXy @XmlPath擴展。
讓我們來看看它的作用。 這是更新的Person POJO。
@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批注,我們不需要Car POJO。 該批注駐留在org.eclipse.persistence.oxm.annotations包中,將其放在類路徑中非常簡單。 如果您是maven用戶,只需添加:
<dependency><groupid>org.eclipse.persistence</groupId><artifactid>eclipselink</artifactId><version>2.3.2</version>
</dependency>
為了告訴您的JDK在運行時將MOXy用于JAXB實現,您放置了一個名為
jaxb.properties與JAXB POJO位于同一目錄中。 它包含一行:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
為了確保您正在使用MOXy實現,只需檢查JAXB上下文:
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
System.out.println("jaxbContext is=" +jaxbContext.toString());
您應該看到類似以下內容:
jaxbContext is=org.eclipse.persistence.jaxb.JAXBContext@5e3974
之后,沒有任何變化。 完全相同的數據編碼都可以使用。
我之所以真正喜歡此擴展的原因之一是因為它意味著更少的代碼。 這通常意味著更簡潔的代碼和更多可維護的代碼。 這在更復雜的情況下變得更加明顯,在這種情況下,實體的層次結構比該簡單示例要深得多。 如果使用XJC之類的東西來生成POJO沒關系,您仍然會感到代碼膨脹。
請記住,JAXB被設置為比JAXP替代品(例如SAX和DOM)更簡潔的編程模型,但是在具有深層次結構的場景中,使用JAXB對類進行概要分析并不能使它令人信服地更加簡潔。 請記住,使用DOM和XPath甚至僅使用SAX來忽略不需要的類將非常容易。
MOXy通過提供對XML文件中的任何內容使用XPath表達式的功能,將清潔的戰斗帶回了JAXB。
注意:MOXy剛剛作為WebLogic 12c的JAXB實現包含在內。
參考文獻:
- MOXy項目頁面
- Blaise Doughan的博客
- 來自都柏林技術博客的 JCG合作伙伴 Alex Staveley 通過MOXy實現使JAXB清潔器
相關文章 :
- 使用JAXB從XSD生成XML
- 重用生成的JAXB類
- 將對象映射到多個XML模式–天氣示例
- JAXB,SAX,DOM性能
- 具有簡單框架教程的Android XML綁定
翻譯自: https://www.javacodegeeks.com/2012/01/make-your-jaxb-cleaner-with-moxy.html