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会混淆使用哪个注释。 对于存在列表的实例,@ XmlElementWrapper用于告诉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

jaxb_JAXB众所周知的秘密相关推荐

  1. JAXB众所周知的秘密

    介绍 我重新发现了Java提供给大众的库. 当我第一次阅读该规范时,我很困惑,以为我需要所有这些特殊工具来实现. 我最近发现,只需要一些注释和一个POJO. 杰克斯 JAXB代表XML绑定的Java体 ...

  2. 在Python中为什么切片要忽略最后一个元素?

    在切片和区间操作里不包含区间范围的最后一个元素是Python 的风格,这个习惯符合Python C和其他语言里以0作为起始下标的传统. 当只有最后一个位置信息时,我们也可以快速看出切片和区间里有一个元 ...

  3. IT行业招聘技巧--渠道篇

    上周就准备开始写招聘技巧的渠道篇,结果码到800字的时候QQ空间突然跳转,内容全丢了.这次就本分一点,用WORD建档开挖吧. 说到招聘渠道,那是HR经理物色招聘人员时必问的问题,很多人都会说,这谁都懂 ...

  4. 货币战争5 读书笔记

    看这本书如果当做故事书,那就看看就好,也很有意思.但是如果想真正理解相关的金融知识,还是需要一定的基础,其中有些逻辑关系特别难梳理,比如说国债回购抵押负利率的现象和原因,不知道是书上没讲清还是我没理解 ...

  5. 外卖平台乱象迭出!究竟谁该负责?

    在刚刚过去的2015年,喧嚣且多变的中国互联网历程上,"外卖"是个绝对不可忽视的细分领域.从上半年多家外卖平台巨额融资的意气风发,到下半年的乱象频出,其历程之曲折离奇,与打车应用. ...

  6. 2004年国内十大暴利行业

    本刊记者 原松华 当我们梳理2004年暴利行业时,却发现所谓的意料之中与意料之外.比如汽车企业的"艳阳天"似乎一夜间走到了尽头.汽车市场价格体系土崩瓦解,降价狂飙席卷全国.经过一轮 ...

  7. zz一篇很赞同的文章:2008年以后房价会降?想都不要想

    摘要: 1.未来大家买房会越来越远,因为近的都太贵了: 2.房价上涨的罪魁祸首不是开发商,是谁自己看. ===================================== 房价问题一直和教 ...

  8. portswigger JWT attacks

    目录 什么是JWTs? JWT格式 JWT vs JWS vs JWE 什么是JWT attacks? JWT 攻击的影响是什么? JWT 攻击漏洞是怎么产生的? <1> Acceptin ...

  9. python之协程与IO操作

    协程 协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B ...

最新文章

  1. php转java知乎_php程序员来谈谈php和java
  2. 程序员能力矩阵 你属于哪一层?
  3. libdgl.dll WinError 126
  4. 贴片铝电容识别及型号_贴片钽电容封装及规格和参数资料
  5. 2013年最值得我们学习的网页作品示例【系列六】
  6. php审计学习:xdcms2.0.8注入
  7. ubuntu linux下建立stm32开发环境: 程序烧录 openocd+openjtag
  8. Android无法优化应用,Android应用优化总结
  9. 走进中国移动(宁夏)数据中心,感受不一样的运营商情怀
  10. matlab怎么显示bfm模型的纹理模型,BFM模型介绍及可视化实现(C++)
  11. pandas查看两个series、list元素的包含关系(查看一个series的每个元素是否在另一个series中)
  12. 华为P50 Pro外观基本确认:居中开孔全面屏,首发鸿蒙操作系统
  13. css 动画 animate
  14. 令人困惑的strtotime
  15. 自定义一个腾讯云短信验证码接口spring-starter
  16. 2010年6月3日晚18点23分
  17. 硬盘分区无法打开,提示“文件或目录损坏且无法读取”
  18. docker之构建镜像
  19. 内网渗透测试:域内权限维持思路总结
  20. android版本下载京东,京东下载2021安卓最新版_手机app官方版免费安装下载_豌豆荚...

热门文章

  1. 牛客挑战赛43C-最优公式【二分】
  2. 51nod-猴猴吃苹果【线段树】
  3. P1040,jzoj1167-加分二叉树【树形dp】
  4. ssl1202-滑雪【记忆化搜索法】
  5. P3565 [POI2014]HOT-Hotels(树形dp+长链剖分)
  6. 【LCT】魔法森林(P2387)
  7. 【线段树】【LCT】【LCA】树点涂色(luogu 3703)
  8. codeforces gym-101745 D-Stamp Stamp Stamp动态规划
  9. JavaFX触屏事件
  10. Redis 5.0 正式版发布了,19 个新特性