jaxb_JAXB众所周知的秘密
jaxb
介紹
我重新發(fā)現(xiàn)了Java向大眾提供的庫(kù)。 當(dāng)我第一次閱讀該規(guī)范時(shí),我很困惑,以為我需要所有這些特殊工具來(lái)實(shí)現(xiàn)。 我最近發(fā)現(xiàn),只需要一些注釋和一個(gè)POJO。
杰克斯
JAXB代表XML綁定的Java體系結(jié)構(gòu)。 這種體系結(jié)構(gòu)允許開發(fā)人員將來(lái)自類的數(shù)據(jù)轉(zhuǎn)換為XML表示形式。 這稱為編組。 該體系結(jié)構(gòu)還允許開發(fā)人員逆轉(zhuǎn)將XML表示轉(zhuǎn)換為類的過(guò)程。 這稱為解組。 有一些工具可以從XML Schema文件創(chuàng)建Java類。 該工具稱為xjc。 還有另一種使用schemagen創(chuàng)建xsd文件的工具。
編組
在Java中,編組和解組會(huì)發(fā)生在幾個(gè)地方。 我首先接觸到的是RMI。 對(duì)象通過(guò)用作遠(yuǎn)程方法調(diào)用的參數(shù)而發(fā)送,因此稱為遠(yuǎn)程方法調(diào)用(RMI)。 它發(fā)生的另一個(gè)地方是將對(duì)象寫入流。 實(shí)現(xiàn)此功能的流是ObjectOutputStream和ObjectInputStream。 發(fā)生的另一個(gè)地方是ORM類。 當(dāng)然,另一種方式是編寫實(shí)例的XML表示。 想要編組的類需要實(shí)現(xiàn)Serializable,并且其所有成員屬性也都需要實(shí)現(xiàn)Serializable,但通過(guò)JAXB的類除外。 可序列化是標(biāo)記接口。 它沒(méi)有實(shí)現(xiàn)的方法,但是它表明可以對(duì)類進(jìn)行序列化或編組。 被編組的對(duì)象的數(shù)據(jù)已采用某種持久化方式。 未編組對(duì)象的數(shù)據(jù)已從持久狀態(tài)讀取并與一個(gè)類連接。 這使得類路徑非常重要。 有趣的是,類路徑中的有效條目是http:// ip:port / path / to / jar 。 我想有些組織會(huì)通過(guò)集中化jar文件來(lái)使用此功能,而最新版本僅需下載即可。
例
我用maven和spring來(lái)做這個(gè)例子。 原因不是使它變得更復(fù)雜,而是使代碼更易于閱讀和更專注于使用我所展示的技術(shù)。 pom.xml文件中的依賴項(xiàng)如下:
<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是三個(gè)集合中的中心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定義這是一個(gè)類的開始。 @XmlAccessorType(XmlAccessType.FIELD)告訴體系結(jié)構(gòu),這些字段將用于定義xml中的元素。 注釋也可以放在吸氣劑上。 如果未使用注釋,則JAXB會(huì)混淆使用哪個(gè)注釋。 對(duì)于存在列表的實(shí)例,@ XmlElementWrapper用于告訴JAXB外部標(biāo)簽將是什么。 例如,有一個(gè)地址列表。 包裝器使用名為“ name”的參數(shù),并用“ addresss”填充。 呈現(xiàn)XML時(shí),將在地址集合周圍包裹標(biāo)簽“ addresses”。 如果要更改屬性的標(biāo)記,則使用@XmlElement批注。 回到我們的地址列表,注釋將地址列表重新定義為“ address”。 這將導(dǎo)致每個(gè)地址對(duì)象都具有“地址”標(biāo)簽,而不是已經(jīng)占用的“地址”標(biāo)簽。 數(shù)字使用相同的模式。 其余的屬性將具有與它們的名稱匹配的標(biāo)簽。 例如,lastName將變成標(biāo)簽“ lastName”。 其他兩個(gè)POJO(電話號(hào)碼.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一類有限數(shù)量的值。 它帶有一個(gè)名稱參數(shù)。 最后一個(gè)POJO還使用@XmlType定義其公共枚舉類。 可以在Address.java中找到它。
放在一起
有了所有這些注釋和類定義,是時(shí)候?qū)⑺羞@些放到一個(gè)主類中了。 這是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檢索聯(lián)系人實(shí)例。 其次,以Contact類作為根類創(chuàng)建一個(gè)JAXBContext實(shí)例。 上下文將分析類結(jié)構(gòu),并創(chuàng)建可以封送或拆封Contact,Address和PhoneNumber類的上下文。 在下一部分中,從JAXBContext創(chuàng)建一個(gè)編組器。 Marshaller.JAXB_FORMATTED_OUTPUT屬性設(shè)置為true。 這將創(chuàng)建一個(gè)格式化的XML輸出。 如果未設(shè)置該屬性,則XML將作為一行文本出現(xiàn)。 調(diào)用編組器進(jìn)行編組聯(lián)系并將其寫入StringWriter。 然后將XML打印到System.out。 輸出應(yīng)如下所示:
<?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與其數(shù)據(jù)一起解組到Contact實(shí)例中。 Unmarshaller由JAXBContext創(chuàng)建。 接下來(lái),解組器將傳遞一個(gè)StringReader,其內(nèi)容為剛剛創(chuàng)建的XML。 解組器返回一個(gè)對(duì)象,該對(duì)象被強(qiáng)制轉(zhuǎn)換為聯(lián)系人。 將針對(duì)新的Contact實(shí)例測(cè)試Contact的原始實(shí)例,以查看它們是否等效。 輸出應(yīng)顯示:
Are the instances equivalent: true.摘要
在此示例中,Contact的實(shí)例被轉(zhuǎn)換為XML,并且在JAXB的幫助下,所得的XML被轉(zhuǎn)換回Contact實(shí)例。 JAXB是將對(duì)象的狀態(tài)映射到XML并將XML映射回對(duì)象的體系結(jié)構(gòu)。
參考資料
- 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
總結(jié)
以上是生活随笔為你收集整理的jaxb_JAXB众所周知的秘密的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 华为电脑配置如何选择?
- 下一篇: gtest 测试部分_全部关于测试–第2
