元件使用總結:使用 JAXB 實現 XML檔案和java物件互轉
JAXB是一個業界的標準,實現XML檔案和Java物件的互轉。 JAXB是JDK 的組成部分。我們不需要下載第三方jar包 即可做到輕鬆轉換。 複製程式碼
重要類和介面:
○ JAXBContext類,是應用的入口,用於管理XML/Java繫結資訊。 ○ Marshaller介面,將Java物件序列化為XML資料。 ○ Unmarshaller介面,將XML資料反序列化為Java物件。 複製程式碼
註解
從XML到Java物件的註解: ○ @XmlType: ○ @XmlElement :將java物件的屬性對映為xml的節點 ○ @XmlRootElement:此類對應xml的根元素 ○ @XmlAttribute :把java物件的屬性對映為xml的屬性 ○ @XmlAccessorType :用於指定由java物件生成xml檔案時對java物件屬性的訪問方式 ○ @XmlJavaTypeAdapter :在轉換比較複雜的物件時,如map型別或者格式化日期等。使用此註解時,需要自己寫一個XmlAdapter類 從Java物件到XML的註解: ○ @XmlAccessorOrder :對java物件生成的xml元素進行排序 ○ @XmlTransient :定義某一欄位或屬性不需要被對映為XML ○ @XmlElementWrapper :為陣列元素或集合元素定義一個父節點 複製程式碼
工程實現
demo1:演示xml基本用法,演示@XmlRootElement 、@XmlAccessorType、@XmlElement的用法
基礎POJO類ClassRoomModel包含一個變數name和變數StudentModel列表
public class StudentModel { private int id; // 學號 private String name; // 名稱 private String sex; // 性別 } @XmlRootElement(name = "classRoom") @XmlAccessorType(value = XmlAccessType.FIELD) public class ClassRoomModel { @XmlElement(name="name") private String name; @XmlElement(name="student") private List<StudentModel> studentModelList; } 複製程式碼
待轉化classroom.xml
<?xml version="1.0" encoding="UTF-8"?> <classRoom> <name>配置總名稱</name> <student> <id>1</id> <name>張三</name> <sex>男</sex> </student> <student> <id>2</id> <name>李四</name> <sex>女</sex> </student> </classRoom> 複製程式碼
測試類JAXBManager: 建立JAXBContext物件,根據JAXBContext物件建立Unmarshaller 物件,使用Unmarshaller 物件實現將xml轉化為ClassRoomModel物件。 根據JAXBContext物件建立Marshaller 物件,使用Marshaller 實現將ClassRoomModel 物件轉化為xml檔案
JAXBContext jaxbContext = JAXBContext.newInstance(ClassRoomModel.class); // 從xml檔案中讀取,並轉化為java物件 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); InputStream classRoomInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/hry/java/xml/classroom.xml"); System.out.println(JAXBManager.class.getClassLoader().getResource("")); System.out.println(Thread.currentThread().getContextClassLoader().getResource("")); ClassRoomModel classRoomModel = (ClassRoomModel)unmarshaller.unmarshal(classRoomInputStream); System.out.println(JSON.toJSONString(classRoomModel)); // 儲存檔案,將Java物件轉化為xml檔案 Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(classRoomModel, new File("classroon-save.xml")); 複製程式碼
demo2: 演示@XmlAttribute、@XmlJavaTypeAdapter、XmlAdapter用法
基礎POJO類:ClassRoomModel2包含一個變數name和變數StudentModel列表 此demo和上面的類不同,StudentModel2 是使用@XmlAttribute通過xml元素的屬性注入值,另外增加屬性Date物件
@XmlAccessorType(value = XmlAccessType.FIELD) public class StudentModel2 { @XmlAttribute(name = "id") private int id; // 學號 @XmlAttribute(name = "name") private String name; // 名稱 @XmlAttribute(name = "sex") private String sex; // 性別 @XmlAttribute(name = "birthDate") @XmlJavaTypeAdapter(value = DateXmlAdapter.class) // 配置日期轉化器 private Date birthDate; // 生日 } @XmlRootElement(name = "classRoom") @XmlAccessorType(value = XmlAccessType.FIELD) public class ClassRoomModel2 { @XmlElement(name="name") private String name; @XmlElement(name="student") private List<StudentModel2> studentModelList; } 複製程式碼
待轉化xml檔案
<?xml version="1.0" encoding="UTF-8"?> <classRoom> <name>配置總名稱</name> <student id="1" name="張三" sex="男" birthDate="1999-10-22" /> <student id="2" name="李四" sex="女" birthDate="1997-12-23"/> </classRoom> 複製程式碼
XmlAdapter用法:StudentModel2 裡的成員變數birthDate的新註解@XmlJavaTypeAdapter(value = DateXmlAdapter.class),實現日期String和Date的相互轉化
public class DateXmlAdapter extends XmlAdapter<String, Date> { // 時間 private static final ThreadLocal<SimpleDateFormat> simpleDateFormatThreadLocalYYYYMMDD = new ThreadLocal<SimpleDateFormat>(){ @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd"); } }; @Override public Date unmarshal(String v) throws Exception { System.out.println(v); return simpleDateFormatThreadLocalYYYYMMDD.get().parse(v); } @Override public String marshal(Date v) throws Exception { System.out.println(v); return simpleDateFormatThreadLocalYYYYMMDD.get().format(v); } } 複製程式碼
測試類JAXBManager:用法和第一個demo相同,詳細見程式碼
public static void main(String[] args){ try { JAXBContext jaxbContext = JAXBContext.newInstance(ClassRoomModel2.class); // 從xml檔案中讀取,並轉化為java物件 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); InputStream classRoomInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/hry/java/xml/classroom2.xml"); System.out.println(JAXBManager2.class.getClassLoader().getResource("")); System.out.println(Thread.currentThread().getContextClassLoader().getResource("")); ClassRoomModel2 classRoomModel = (ClassRoomModel2)unmarshaller.unmarshal(classRoomInputStream); System.out.println(JSON.toJSONString(classRoomModel)); // 儲存檔案,將Java物件轉化為xml檔案 Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(classRoomModel, new File("classroon-save2.xml")); } catch (JAXBException e) { e.printStackTrace(); } } 複製程式碼
異常處理
如果不在類加上@XmlAccessorType(value = XmlAccessType.FIELD),則可能丟擲如下異常。@XmlAccessorType的預設訪問級別是XmlAccessType.PUBLIC_MEMBER,因此,如果java物件中的private成員變數設定了public許可權的getter/setter方法,就不要在private變數上使用@XmlElement和@XmlAttribute註解,否則在由java物件生成xml時會報同一個屬性在java類裡存在兩次的錯誤,異常如下:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions 類的兩個屬性具有相同名稱 "name" this problem is related to the following location: at public java.lang.String com.hry.java.xml.model.ClassRoomModel.getName() at com.hry.java.xml.model.ClassRoomModel this problem is related to the following location: at private java.lang.String com.hry.java.xml.model.ClassRoomModel.name at com.hry.java.xml.model.ClassRoomModel 複製程式碼