JAXB众所周知的秘密
介紹
我重新發現了Java提供給大眾的庫。 當我第一次閱讀該規范時,我很困惑,以為我需要所有這些特殊工具來實現。 我最近發現,只需要一些注釋和一個POJO。
杰克斯
JAXB代表XML綁定的Java體系結構。 這種體系結構允許開發人員將來自類的數據轉換為XML表示形式。 這稱為編組。 該體系結構還允許開發人員逆轉將XML表示轉換為類的過程。 這稱為解組。 有一些工具可以從XML Schema文件創建Java類。 該工具稱為xjc。 還有另一種使用schemagen創建xsd文件的工具。
編組
編組和解組在Java中發生了很多地方。 我首先接觸到的是RMI。 對象被發送用作遠程方法調用的參數,因此名稱為“遠程方法調用(RMI)”。 它發生的另一個地方是將對象寫入流。 實現此功能的流是ObjectOutputStream和ObjectInputStream。 發生的另一個地方是ORM類。 當然,另一種方式是編寫實例的XML表示。 想要編組的類需要實現Serializable,并且其所有成員屬性也都需要實現Serializable,但通過JAXB的類除外。 可序列化是標記接口。 它沒有實現的方法,但是它表明可以對類進行序列化或編組。 被編組的對象的數據已采用某種持久化方式。 未編組對象的數據已從持久狀態讀取并與類連接。 這使得類路徑非常重要。 有趣的是,類路徑中的有效條目是http:// ip:port / path / to / jar 。 我想有些組織可以通過集中化jar文件來使用此功能,而最新版本僅需下載即可。
例
我用maven和spring來做這個例子。 原因不是使它更加復雜,而是使代碼更清晰地閱讀和更專注于使用我所展示的技術。 pom.xml文件中的依賴項如下:
<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>com.sun.xml.bind</groupId><artifactId>jaxb-impl</artifactId><version>2.2.8-b01</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>3.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>3.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>3.2.3.RELEASE</version></dependency></dependencies>JAXB的妙處在于它使用POJO。 Contact.java是三個集合中的中心POJO類。
package org.mathison.jaxb.beans;import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Contact {private String lastName;private String firstName;private String middleName;private String jobTitle;@XmlElementWrapper(name = "addresses")@XmlElement(name = "address")private List<Address> addresses;@XmlElementWrapper(name = "phone-numbers")@XmlElement(name = "phone-number")private List<PhoneNumber> numbers;public String getLastName() {return lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getMiddleName() {return middleName;}public void setMiddleName(String middleName) {this.middleName = middleName;}public String getJobTitle() {return jobTitle;}public void setJobTitle(String jobTitle) {this.jobTitle = jobTitle;}public List<Address> getAddresses() {return addresses;}public void setAddresses(List<Address> addresses) {this.addresses = addresses;}public List<PhoneNumber> getNumbers() {return numbers;}public void setNumbers(List<PhoneNumber> numbers) {this.numbers = numbers;}@Overridepublic String toString() {return "Contact{" + "lastName=" + lastName + ", firstName=" + firstName + ", middleName=" + middleName + ", jobTitle=" + jobTitle + ", addresses=" + addresses + ", numbers=" + numbers + '}';}@Overridepublic int hashCode() {int hash = 3;hash = 23 * hash + (this.lastName != null ? this.lastName.hashCode() : 0);hash = 23 * hash + (this.firstName != null ? this.firstName.hashCode() : 0);hash = 23 * hash + (this.middleName != null ? this.middleName.hashCode() : 0);hash = 23 * hash + (this.jobTitle != null ? this.jobTitle.hashCode() : 0);hash = 23 * hash + (this.addresses != null ? this.addresses.hashCode() : 0);hash = 23 * hash + (this.numbers != null ?this.numbers.hashCode() : 0);return hash;}@Overridepublic boolean equals(Object obj) {if (obj == null) {return false;}if (getClass() != obj.getClass()) {return false;}final Contact other = (Contact) obj;if ((this.lastName == null) ? (other.lastName != null) :!this.lastName.equals(other.lastName)) {return false;}if ((this.firstName == null) ? (other.firstName != null) : !this.firstName.equals(other.firstName)) {return false;}if ((this.middleName == null) ? (other.middleName != null) : !this.middleName.equals(other.middleName)) {return false;}if ((this.jobTitle == null) ? (other.jobTitle != null) : !this.jobTitle.equals(other.jobTitle)) {return false;}if(!listEquals(this.addresses, other.addresses)) {return false;}if(!listEquals(this.numbers, other.numbers)) {return false;}return true;}private boolean listEquals(List first, List second) {for(Object o: first) {if(!second.contains(o)) {return false;}}return true;}}要看的主要部分是注釋。 @XmlRootElement定義這是一個類的開始。 @XmlAccessorType(XmlAccessType.FIELD)告訴體系結構,這些字段將用于定義xml中的元素。 注釋也可以放在吸氣劑上。 如果未使用注釋,則JAXB會混淆使用哪個注釋。 對于存在列表的實例,@Xm??lElementWrapper用來告訴JAXB外部標簽將是什么。 例如,有一個地址列表。 包裝器采用名為“ name”的參數,并用“ addresss”填充。 呈現XML時,將在地址集合周圍包裹標簽“ addresses”。 如果要更改屬性的標記,則使用@XmlElement批注。 回到我們的地址列表,注釋將地址列表重新定義為“ address”。 這將導致每個地址對象都具有“地址”標簽,而不是已經占用的“地址”標簽。 數字使用相同的模式。 其余的屬性將具有與它們的名稱匹配的標簽。 例如,lastName將變成標簽“ lastName”。 其他兩個POJO(電話號碼.java和地址.java)具有公共枚舉類。 這是PhoneNumber.java:
package org.mathison.jaxb.beans;import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType;@XmlRootElement public class PhoneNumber {@XmlType(name="phone-type")public enum Type {HOME,WORK,HOME_FAX,WORK_FAX;}private Type type;private String number;public Type getType() {return type;}public void setType(Type type) {this.type = type;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}@Overridepublic String toString() {return "PhoneNumber{" + "type=" + type + ", number=" + number + '}';}@Overridepublic int hashCode() {int hash = 7;hash = 37 * hash + (this.type != null ? this.type.hashCode() : 0);hash = 37 * hash + (this.number != null ? this.number.hashCode() : 0);return hash;}@Overridepublic boolean equals(Object obj) {if (obj == null) {return false;}if (getClass() != obj.getClass()) {return false;}final PhoneNumber other = (PhoneNumber) obj;if (this.type != other.type) {return false;}if ((this.number == null) ? (other.number != null) : !this.number.equals(other.number)) {return false;}return true;}}注釋的注釋為@XmlType。 這告訴JAXB一類有限數量的值。 它帶有一個名稱參數。 最后一個POJO還使用@XmlType定義其公共枚舉類。 可以在Address.java中找到它。
全部放在一起
有了所有這些注釋和類定義,是時候將所有這些放到一個主類中了。 這是App.java,主要類:
package org.mathison.jaxb.app;import java.io.StringReader; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.mathison.jaxb.beans.Contact; import org.springframework.context.ApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext;public class App {public static void main( String[] args ){ApplicationContext cxt = new GenericXmlApplicationContext("jaxb.xml");Contact contact = cxt.getBean("contact", Contact.class);StringWriter writer = new StringWriter();try {JAXBContext context = JAXBContext.newInstance(Contact.class);//create xml from an instance from ContactMarshaller m = context.createMarshaller();m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);m.marshal(contact, writer);String xml = writer.getBuffer().toString();System.out.println(xml);//Take xml to ContactStringReader reader = new StringReader(xml);Unmarshaller u = context.createUnmarshaller();Contact fromXml = (Contact)u.unmarshal(reader);System.out.println("Are the instances equivalent: " + contact.equals(fromXml));} catch(Exception e){e.printStackTrace();}} }首先,從ApplicationContext檢索聯系人實例。 其次,以Contact類作為根類創建JAXBContext實例。 上下文將分析類結構,并創建可以封送或拆封Contact,Address和PhoneNumber類的上下文。 在下一部分中,從JAXBContext創建一個編組器。 Marshaller.JAXB_FORMATTED_OUTPUT屬性設置為true。 這將創建一個格式化的XML輸出。 如果未設置該屬性,則XML將作為一行文本出現。 調用編組器進行編組聯系并將其寫入StringWriter。 然后將XML打印到System.out。 輸出應如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <contact><lastName>Mathison</lastName><firstName>Daryl</firstName><middleName>Bob</middleName><jobTitle>Developer</jobTitle><addresses><address><addressLine>123 Willow View</addressLine><city>Cibolo</city><state>TX</state><type>HOME</type><zipCode>78228</zipCode></address><address><addressLine>411 Grieg</addressLine><city>San Antonio</city><state>TX</state><type>WORK</type><zipCode>78228</zipCode></address></addresses><phone-numbers><phone-number><number>210-123-4567</number><type>WORK</type></phone-number><phone-number><number>210-345-1111</number><type>HOME</type></phone-number></phone-numbers></contact>在下一部分中,將xml與其數據一起解組到Contact實例中。 Unmarshaller由JAXBContext創建。 接下來,解組器將傳遞一個StringReader,其內容為剛剛創建的XML。 解組器返回一個對象,該對象被強制轉換為聯系人。 將針對新的Contact實例測試Contact的原始實例,以查看它們是否等效。 輸出應顯示:
Are the instances equivalent: true.摘要
在此示例中,Contact的實例被轉換為XML,并且在JAXB的幫助下,所得的XML被轉換回Contact實例。 JAXB是一種將對象的狀態映射到XML并將XML映射回對象的體系結構。
參考文獻
- http://www.techrepublic.com/blog/programming-and-development/jaxb-20-offers-improved-xml-binding-in-java/498
- http://www.vogella.com/articles/JAXB/article.html
- http://en.wikipedia.org/wiki/JAXB
翻譯自: https://www.javacodegeeks.com/2014/10/the-jaxb-well-known-secret.html
總結
以上是生活随笔為你收集整理的JAXB众所周知的秘密的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神圣骑士天赋教练(wow9.0神圣骑士天
- 下一篇: 全部关于测试–第2部分