java学习
JAXB
JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。
JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。
Marshaller接口,将Java对象序列化为XML数据。
Unmarshaller接口,将XML数据反序列化为Java对象。
@XmlType,将Java类或枚举类型映射到XML模式类型
@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标注)字段到XML。其他值还有XmlAccessType.PROPERTY和XmlAccessType.NONE。
@XmlAccessorOrder,控制JAXB 绑定类中属性和字段的排序。
@XmlJavaTypeAdapter,使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。
@XmlElementWrapper ,对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。
@XmlRootElement,将Java类或枚举类型映射到XML元素。
@XmlElement,将Java类的一个属性映射到与属性同名的一个XML元素。
@XmlAttribute,将Java类的一个属性映射到与属性同名的一个XML属性。
其他:
对于要序列化(marshal)为XML的Java类,绝不能把成员变量声明为public,否则运行将抛出异常com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException。
对于JAXB相关的重要Annotation的声明,如@Xml.....,可以放在成员变量的setter()或getter()方法上,两者中任选其一即可,但决不能放在成员变量上,否则运行将抛出异常com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException。
简单例子
package model;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
@XmlType(propOrder = {})
@XmlRootElement(name = "user")
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
public class User implements Serializable {
private String userName;
private int age;
private String role;
private String bibi;
public User() {
}
public User(String userName, int age, String role, String bibi) {
this.userName = userName;
this.age = age;
this.role = role;
this.bibi = bibi;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@XmlAttribute
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@XmlElement
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@XmlTransient
public String getBibi() {
return bibi;
}
public void setBibi(String bibi) {
this.bibi = bibi;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", age=" + age +
", role='" + role + '\'' +
", bibi='" + bibi + '\'' +
'}';
}
}
package model;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.junit.Test;
public class testMain {
@Test
public static void saveXmlTest() {
User user = new User("陈本布衣", 2018, "超级管理员","瞎哔哔");
user.setBibi("bibi");
File file = new File("D://user.xml");
try {
JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
Marshaller marshaller = jaxbContext.createMarshaller();
//格式化输出,即按标签自动换行,否则就是一行输出
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//设置编码(默认编码就是utf-8)
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
//是否省略xml头信息,默认不省略(false)
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
marshaller.marshal(user, file);
} catch (JAXBException e) {
e.printStackTrace();
}
}
@Test
public static void getUserTest() {
File file = new File("D://user.xml");
try {
JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
User user = (User) unmarshaller.unmarshal(file);
System.out.println(user.toString());
} catch (JAXBException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
testMain.saveXmlTest();
testMain.getUserTest();
}
}
① 简单对象处理
@XmlType(propOrder = {"userName","role","menu"})
@XmlRootElement(name = "user")
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
public class User implements Serializable {
private String userName;
private int age;
private String role;
private String bibi;
private Menu menu;
public User() {
}
public User(String userName, int age, String role, String bibi) {
this.userName = userName;
this.role = role;
this.age = age;
this.bibi = bibi;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
@XmlAttribute
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@XmlElement(nillable=true)
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
@XmlTransient
public String getBibi() {
return bibi;
}
public void setBibi(String bibi) {
this.bibi = bibi;
}
@XmlElement
public Menu getMenu() {
return menu;
}
public void setMenu(Menu menu) {
this.menu = menu;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", age=" + age +
", role='" + role + '\'' +
", menu=" + menu +
'}';
}
}
//菜单对象
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Menu {
private String name;
private String id;
public Menu() {
}
public Menu(String name, String id) {
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Menu{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
'}';
}
}
② 集合处理
@XmlElementWrapper自定义一个包装节点,这样产生的XML文档才更有层次:
③ 格式化处理
业务数据中日期、数值通常是必不可少的,在数据存储的时候,这些数据通常都需要做格式化处理,比如将日期格式化,货币型数值处理等等。JAXB中格式化处理需要继承适配器抽象类XmlAdapter,并覆写其序列化和反序列化的方法
问题补充
上述博文中描述的工具方法仅仅是出于学习中追根问本的目的写得稍微冗余了些,实际上,我所知道的是最迟从jdk1.7开始,JAXB就对解组和编组的方法进行了更简单的封装,所以,实际项目中除非自己要进行个性化设置,否则大可不用自己再创建JAXBContext实例,直接通过JAXB静态调用相应的工具方法就行了,有兴趣的看官稍微跟踪一下源码就能了然,于是上面的工具方法可以写得更简单
package util;
import javax.xml.bind.JAXB;
import java.io.File;
public class JaxbUtil {
public static void convertToXml(Object obj, File file) {
JAXB.marshal(obj,file);
}
public static <T> T convertToJavaBean(Class<T> clz, File file) {
return JAXB.unmarshal(file, clz);
}
}
上一篇: JAVA枚举简介