使用JAXB类库实现JAVA对象与XML互转
2016-06-07 14:14
676 查看
XML是开发中常用的配置文件类型,在常用的组件包里也能时常看到它的踪影,如Spring中的applicationContext.xml、Hibernate中的hbm.xml,都是用的XML来配置相关的参数信息。可见其使用是十分广泛的。
但是在Java中,要解析一个XML,并封装为一个对象,可能大家首先会想到Dom4j、Jdom等第三方类库,使用其中的解析器对每一个节点解析,并生成自己想要的对象。这样写的话,代码显得是很混乱,不是很易读。如果在Webservice交互中,用到XML传递数据,那么工作量就会更大了。
今天就要用一个非常好用的工具来解决这个问题。它就是JAXB类库。
JAXB允许JAVA开发人员将JAVA类映射为XML,也可以逆向的将XML转换为JAVA。可以不用手动的去写解析XML的方法,只需要书写对应的JAVA Bean,并配置好相应的注解,就可以完成转换,大大简化了程序员的工作量。
讲了这么多,大家可能在想,如何集成呢,其实咱们不用集成就可以使用,这个功能是直接集成在JDK中的。完全不用集成,是不更简单呢,不用集成任何类库。
JAXB实现转换是依赖于Annotation的,那么咱们应该如何使用呢,可以看下面各个Annotation的作用:
a)、@XmlRootElement
用来定义一个XML的根节点信息,其参数有name和namespace。
其中name用来定义根节点的名称,非必填。
namespace用来定义XML的命名空间,非必填。
例如下定义:
如果咱们定义了一个JAVA Bean,名叫Property:
Java
1.咱们给他加上@XmlRootElement信息:Java
那么用表明生成的XML的根节点就是类名的小写,如下:
XHTML
2.如果定义了name信息,则根节点名称就会是你定义的名称:Java
生成的XML如下:
XHTML
3.如果定义了namespace,根节点就会显示出你定义的namespace,如下代码Java
生成的XML如下
XHTML
b)、@XmlAccessorType控制字段或属性的序列化。常用的有XmlAccessType.FIELD、XmlAccessType.PROPERTY和XmlAccessType.NONE。如果定义的是FIELD(全自动),则表明JAXB 绑定类中的每个非静态(static)、非瞬态(transient)字段将会自动绑定到 XML,除非由 XmlTransient 注释。如果定义的是PROPERTY(半自动),则表明JAXB 绑定类中的每个获取方法(get)/设置方法(set)对将会自动绑定到 XML,除非由 XmlTransient 注释。需要注意的是要实现get/set方法。如果定义的是NONE(手动),则表所有字段或属性都不能绑定到 XML,除非使用一些 JAXB 注释专门对它们进行注释。如果使用了这个属性,咱们就需要对每个要映射的成员变量做设置才可以。1.XmlAccessType.FIELDJava
生成的xml如下
Java
2.XmlAccessType.PROPERTY如果咱们定义的时候不生成get/set方法,看看效果。Java
输出结果
Java
可以看到没有生成name的内容。咱们现在生成get/set方法,再看看效果。Java
生成XML的结果如下
Java
可以看到,这个类型是和get/set方法是否存在相关,如果写get/set方法,就生成xml。c)、@XmlElement将Java类的一个属性映射到与属性同名的一个XML元素。例如上面的例子,生成的是一个子标签。Java
d)、@XmlAttribute
将Java类的一个属性映射到与属性同名的一个XML属性。
Java
如上,name是在Test标签内部,当作Test标签的一个属性。e)、@XmlElementWrapper对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。f)、@XmlTransient阻止将 JavaBean 属性映射到 XML 表示形式。主要用来解决映射冲突的情况。
咱们先分析一下这个XML,可以看到这个XML的根节点是property。其中有个属性是type。其下面有两个标签,分别是key和value。那么咱们可以先定义一个bean。
Java
现在咱们先定义一下根节点,根节点咱们使用@XmlRootElement注解。这样配置@XmlRootElement(name="property")。上面的XML里有一个属性type,咱们可以使用@XmlAttribute(name = "type")来标注type的成员变量对于name和value这两个成员变量,可以使用@XmlElement来标注。那么咱们的JAVA Bean可以改成这样。Java
咱们现在写一个调用的测试类。如:
Java
是不是很简单,完全没有解析XML的代码。
输出结果XHTML
Java
结果如下:XHTML
咱们可以针对上面两种转换的方式写一个工具类,如下:
Java
上面的这个工具类就可以方便的把一个JAVA转换为一个XML字符串,也可以把一个XML字符串或者一个XML输入流转换成一个JAVA对象了。调用的时候也很简单。Java
但是在Java中,要解析一个XML,并封装为一个对象,可能大家首先会想到Dom4j、Jdom等第三方类库,使用其中的解析器对每一个节点解析,并生成自己想要的对象。这样写的话,代码显得是很混乱,不是很易读。如果在Webservice交互中,用到XML传递数据,那么工作量就会更大了。
今天就要用一个非常好用的工具来解决这个问题。它就是JAXB类库。
一、介绍
JAXB允许JAVA开发人员将JAVA类映射为XML,也可以逆向的将XML转换为JAVA。可以不用手动的去写解析XML的方法,只需要书写对应的JAVA Bean,并配置好相应的注解,就可以完成转换,大大简化了程序员的工作量。
二、集成
讲了这么多,大家可能在想,如何集成呢,其实咱们不用集成就可以使用,这个功能是直接集成在JDK中的。完全不用集成,是不更简单呢,不用集成任何类库。
三、前置学习
JAXB实现转换是依赖于Annotation的,那么咱们应该如何使用呢,可以看下面各个Annotation的作用:a)、@XmlRootElement
用来定义一个XML的根节点信息,其参数有name和namespace。
其中name用来定义根节点的名称,非必填。
namespace用来定义XML的命名空间,非必填。
例如下定义:
如果咱们定义了一个JAVA Bean,名叫Property:
Java
1 | public class Property {} |
1 2 | @XmlRootElement public class Property {} |
XHTML
12 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?><property/> |
1 2 3 | @XmlRootElement(name="Test") public class Property { } |
XHTML
12 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Test/> |
1 2 | @XmlRootElement(name = "Test", namespace = "com.jialeens") public class Property {} |
XHTML
12 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Test xmlns="com.jialeens"/> |
1 2 3 4 5 | @XmlRootElement(name = "Test") @XmlAccessorType(XmlAccessType.FIELD) public class Property { public String name; } |
Java
1234 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Test> <name>a</name></Test> |
1 2 3 4 5 | @XmlRootElement(name = "Test") @XmlAccessorType(XmlAccessType.PROPERTY) public class Property { public String name; } |
Java
12 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Test/> |
1 2 3 4 5 6 7 8 9 10 11 12 13 | @XmlRootElement(name = "Test") @XmlAccessorType(XmlAccessType.PROPERTY) public class Property { public String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } |
Java
1234 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Test> <name>a</name></Test> |
1 2 3 4 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Test> <name>a</name> </Test> |
将Java类的一个属性映射到与属性同名的一个XML属性。
Java
123 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Test name="a"></Test> |
四、简单使用
上面说了这么多,大家可能还不是很理解到底应该怎么用,下面咱们来讲一个简单的例子。XML-->JAVA
现在咱们有一段XML。如下结构。Java1 2 3 4 5 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <property type="string"> <key>testKey</key> <value>testValue</value> </property> |
Java
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 | public class Property { /** * 键 */ private String key; /** * 值 */ private String value; /** * 类型 */ private String type; /** * @return the key */ public String getKey() { return key; } /** * @param key * the key to set */ public void setKey(String key) { this.key = key; } /** * @return the value */ public String getValue() { return value; } /** * @param value * the value to set */ public void setValue(String value) { this.value = value; } /** * @return the type */ public String getType() { return type; } /** * @param type * the type to set */ public void setType(String type) { this.type = type; }} |
1 2 3 4 5 6 7 8 9 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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement public class Property { /** * 键 */ @XmlElement(name = "key") private String key; /** * 值 */ @XmlElement(name = "value") private String value; /** * 类型 */ @XmlAttribute(name = "type") private String type; /** * @return the key */ public String getKey() { return key; } /** * @param key * the key to set */ public void setKey(String key) { this.key = key; } /** * @return the value */ public String getValue() { return value; } /** * @param value * the value to set */ public void setValue(String value) { this.value = value; } /** * @return the type */ public String getType() { return type; } /** * @param type * the type to set */ public void setType(String type) { this.type = type; } } |
Java
12345678910111213141516 | public class JaxbTest { @Test public void test() throws JAXBException, IOException { String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + "<property type=\"string\">" + "<key>testKey</key>" + "<value>testValue</value>" + "</property>"; JAXBContext context; context = JAXBContext.newInstance(Property.class); Unmarshaller unmarshal = context.createUnmarshaller(); Property obj = (Property) unmarshal.unmarshal(new StringReader(xml)); System.out.println(obj.getKey()); System.out.println(obj.getValue()); System.out.println(obj.getType()); }} |
输出结果XHTML
1 2 3 | testKey testValue string |
JAVA-->XML
咱们还是用上面的例子来将一个JAVA Bean转换成一个XML,咱们只需要修改调用方法即可,如下。Java
1234567891011121314151617181920 | public class JaxbTest { @Test public void test() throws JAXBException, IOException { Property a = new Property(); a.setKey("testKey"); a.setValue("testValue"); a.setType("string"); ByteArrayOutputStream os = new ByteArrayOutputStream(); try { JAXBContext jc = JAXBContext.newInstance(a.getClass()); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.marshal(a, os); String xml = new String(os.toByteArray(), "UTF-8"); System.out.println(xml); } finally { os.close(); } }} |
1 2 3 4 5 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <property type="string"> <key>testKey</key> <value>testValue</value> </property> |
五、实现一个通用的工具类
咱们可以针对上面两种转换的方式写一个工具类,如下:Java
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 | import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.StringReader; import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBException;import javax.xml.bind.Marshaller;import javax.xml.bind.Unmarshaller; /** * Object<-->XML转换类 * * @param <T> 对应的类 */public class JAXBUtil<T> { /** * 对象转换为xml * * @param element * @return * @throws JAXBException * @throws IOException */ public String marshal(T element) throws JAXBException, IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); try { JAXBContext jc = JAXBContext.newInstance(element.getClass()); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.marshal(element, os); String xml = new String(os.toByteArray(), "UTF-8"); return xml; } finally { os.close(); } } @SuppressWarnings({ "unchecked", "rawtypes" }) public T unmarshal(Class c, String xml) throws JAXBException { JAXBContext context; context = JAXBContext.newInstance(c); Unmarshaller unmarshal = context.createUnmarshaller(); T obj = (T) unmarshal.unmarshal(new StringReader(xml)); return obj; } @SuppressWarnings({ "unchecked", "rawtypes" }) public T unmarshal(Class c, InputStream is) throws JAXBException { JAXBContext context; context = JAXBContext.newInstance(c); Unmarshaller unmarshal = context.createUnmarshaller(); T obj = (T) unmarshal.unmarshal(is); return obj; }} |
1 2 3 4 5 6 7 8 9 10 11 | public class JaxbTest { @Test public void test() throws JAXBException, IOException { Property a = new Property(); a.setKey("testKey"); a.setValue("testValue"); a.setKey("testKey"); JAXBUtil<Property> util = new JAXBUtil<Property>(); System.out.println(util.marshal(a)); } } |
相关文章推荐
- spring-bean的配置
- java中substring的用法
- 字符集略解
- myeclipse
- JAVA设计模式之创建者模式
- java程序想mysql数据库插入数据乱码解决方法()
- java中正则表达式的使用(2)——列出百度搜索的前十项
- spring中@value注解需要注意
- java之包装内---String特殊的包装内
- eclipse插件安装
- Java中有两种包的导入机制
- Thinking in java 笔记
- java中的--------------栈与堆------------------
- 简单实现Java版学生管理系统
- java日期格式转换
- java为什么不能重写静态方法
- Java 关于assert
- Java写到.txt文件,如何实现换行
- java比较两个时间的差值
- java实现文件内容追加