JAXB(Java API for XML Binding),提供了一个快速便捷的方式将Java对象与XML进行转换。在JAX-WS(Java的WebService规范之一)中,JDK1.6 自带的版本JAX-WS2.1,其底层支持就是JAXB。
JAXB 可以实现Java对象与XML的相互转换,在JAXB中,将一个Java对象转换为XML的过程称之为Marshal,将XML转换为Java对象的过程称之为UnMarshal。我们可以通过在 Java 类中标注注解的方式将一个Java对象绑定到一段XML,也就是说,在Java类中标注一些注解,这些注解定义了如何将这个类转换为XML,怎么转换,以及一段XML如何被解析成这个类所定义的对象;也可以使用JAXB的XJC工具,通过定义schema的方式实现Java对象与XML的绑定。
下面来了解一下如何通过标注注解来完成 Marshal 和 UnMarshal 的过程。
首先看个小例子:
定义一个java类
1 package jaxb; 2 3 import javax.xml.bind.annotation.XmlElement; 4 import javax.xml.bind.annotation.XmlRootElement; 5 import javax.xml.bind.annotation.XmlType; 6 7 @XmlType(name = "", propOrder = { 8 "name", 9 "age", 10 "id" 11 }) 12 @XmlRootElement(name="Student") 13 public class Student 14 { 15 @XmlElement(name="ID") 16 public int id = 1; 17 @XmlElement(name="Name") 18 public String name = "ldd"; 19 @XmlElement(name="Age") 20 public int age = 18; 21 @Override 22 public String toString() 23 { 24 return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; 25 } 26 }
Java To XML(Marshal)
1 package jaxb; 2 3 import javax.xml.bind.JAXBContext; 4 import javax.xml.bind.JAXBException; 5 import javax.xml.bind.Marshaller; 6 7 public class JavaToXML 8 { 9 public static void main(String[] args) throws JAXBException 10 { 11 JAXBContext context = JAXBContext.newInstance(Student.class); 12 Marshaller marshaller = context.createMarshaller(); 13 marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");//编码格式 14 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);//是否格式化生成的xml串 15 marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);//是否省略xml头信息(<?xml version="1.0" encoding="gb2312" standalone="yes"?>) 16 Student student = new Student(); 17 marshaller.marshal(student, System.out); 18 } 19 }
输出结果如下:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <Student> <Name>ldd</Name> <Age>18</Age> <ID>1</ID> </Student>
XML To Java(UnMarshal)
1 package jaxb; 2 3 import java.io.File; 4 5 import javax.xml.bind.JAXBContext; 6 import javax.xml.bind.JAXBException; 7 import javax.xml.bind.Unmarshaller; 8 9 10 public class XmlToJava 11 { 12 public static void main(String[] args) throws JAXBException 13 { 14 JAXBContext context = JAXBContext.newInstance(Student.class); 15 Unmarshaller unmarshaller = context.createUnmarshaller(); 16 File file = new File("src/main/java/student.xml"); 17 Student student = (Student) unmarshaller.unmarshal(file); 18 System.out.println(student); 19 } 20 }
如果是一些复杂点的list集合之类的
如果我们预期的xml是这样的:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <userinfo> <list name="user info"> <users id="1"> <name>ldd1</name> <sex>1</sex> </users> <users id="2"> <name>ldd2</name> <sex>2</sex> </users> </list> </userinfo>
首先,定义一个实体类 User
package userdemo; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @XmlAccessorType(XmlAccessType.FIELD) public class User { @XmlAttribute private int id; private String name; private int sex; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } }
特别说明: 如果 @XmlAccessorType()的类型为 XmlAccessType.FIELD,那么@XmlAttribute和@XmlElement的注解就可以放在属性上,否则只能放在get方法上,不然会报错。
下面再定义一个 Users类,目的是为了封装user的list
package userdemo; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @XmlAccessorType(XmlAccessType.FIELD) public class Users { private List<User> users; @XmlAttribute private String name; public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
接下来再定义一个UserInfo实体类,继续包装
package userdemo; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name="userinfo") public class UserInfo { @XmlElement(name="list") private Users users; public Users getUsers() { return users; } public void setUsers(Users users) { this.users = users; } }
准备工作已做好,可以进行测试了
package userdemo; import java.util.ArrayList; import java.util.List; import utils.JaxbUtil; public class UserDemo { public static void main(String[] args) { UserInfo userInfo = new UserInfo(); Users users = new Users(); User user = new User(); user.setId(1); user.setName("ldd1"); user.setSex(1); User user2 = new User(); user2.setId(2); user2.setName("ldd2"); user2.setSex(2); List<User> uList = new ArrayList<User>(); uList.add(user); uList.add(user2); users.setUsers(uList); users.setName("user info"); userInfo.setUsers(users); String string = JaxbUtil.convertToXml(userInfo); System.out.println(string); } }
JaxbUtil类
package utils; import java.io.StringReader; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; public class JaxbUtil { /** * JavaBean转换成xml * 默认编码UTF-8 * @param obj * @param writer * @return */ public static String convertToXml(Object obj) { return convertToXml(obj, "UTF-8"); } /** * JavaBean转换成xml * @param obj * @param encoding * @return */ public static String convertToXml(Object obj, String encoding) { String result = null; try { JAXBContext context = JAXBContext.newInstance(obj.getClass()); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); //xml格式 marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding); //编码 StringWriter writer = new StringWriter(); marshaller.marshal(obj, writer); result = writer.toString(); } catch (Exception e) { e.printStackTrace(); } return result; } /** * xml转换成JavaBean * @param xml * @param c * @return */ @SuppressWarnings("unchecked") public static <T> T converyToJavaBean(String xml, Class<T> c) { T t = null; try { JAXBContext context = JAXBContext.newInstance(c); Unmarshaller unmarshaller = context.createUnmarshaller(); t = (T) unmarshaller.unmarshal(new StringReader(xml)); } catch (Exception e) { e.printStackTrace(); } return t; } }
当然,其实也并不用包装这么层。可以用@XmlElementWrraper注解就可以在某个属性标签外面包裹一层标签。
其实Marshal 和 UnMarshal的过程并不复杂,只需要从JAXBContext中获得Marshaller或Unmarshaller对象,就可以让JAXB帮我们来进行转换了。我们需要操作的主要内容是定义一个规则,告诉JAXB如何将一个类、按照什么样的格式转换为XML,此处暂略过JAXB中主要的一些注解。可自行百度。
由于现在还对这个并不太深入理解,也不知道在合理性上如何,但是实践中还是没啥问题的。