Nội dung tập tin Xml "mobile phone.xml" cần đọc xem tại đây.
JAXB thường được dùng trong trao đổi thông tin giữa các dịch vụ web (Web Service). Dùng JAXB thì ta cần biết đến hai khái niệm Marshalling (hay cũng gọi Serialization) và Unmarshalling (hay còn gọi Deserialization) mà ở đây tôi dịch một cách hình tượng tương ứng là Chuyển xẹp và Chuyển phồng:
- Chuyển xẹp (marshal/serialize): là quá trình chuyển một trạng thái thông tin trong bô nhớ - một cấu trúc dữ liệu (data structure) hay một đối tượng (object) chẳng hạn - sang một dạng thức thông tin nhỏ hơn tức một chuỗi các bit, các byte hay tập tin để có thể lưu trữ hoặc truyền đi.
- Chuyển phồng (unmarshal/deserialize) : là quá trình ngược của chuyển xẹp, nhằm rút ra một cấu trúc dữ liệu hay đối tượng từ một chuỗi các bit, byte hay từ một tập tin.
Để thực hiện việc chuyển xẹp và chuyển phồng này của JAXB, tức chuyển đổi thông tin từ tập tin xml sang các đối tượng Java và ngược lại ta cần viết các lớp (class) định nghĩa đối tượng Java. Trong đó, ta dùng dẫn giải (annotation) của JAXB để tương ứng từng đối tượng Java với từng thành phần (element) của xml. JAXB cung cấp một tiện ích cho phép phát sinh (generate) các lớp này từ một lược đồ XML (XSD).
Nội dung tập tin "mobile phone.xsd" như sau:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="mobile_phones"> <xs:complexType> <xs:sequence> <xs:element name="mobile_phone" maxOccurs="unbounded" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element type="xs:string" name="name" /> <xs:element type="xs:string" name="manufacturer" /> <xs:element type="xs:string" name="os" /> <xs:element type="xs:string" name="description" /> </xs:sequence> <xs:attribute type="xs:string" name="category" use="optional" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
Ta có thế dùng xjc để phát sinh mã từ tập tin xsd bằng cách đánh dòng lệnh đơn giản sau trên màn hình lệnh Command Prompt:
Dòng lệnh trên phát sinh hai lớp MobilePhones.java và ObjectFactory.java trong thư mục D:\Eclipse\Workspace\XmlParse\target\generated
Nghịch một chút, ta cũng có thể dùng Ant để thực hiện việc phát sinh mã này. Dưới đây là tập tin Ant build.xml :
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <project basedir="." default="generate-source" name="XmlParse"> <property environment="env"/> <property name="dir.resources" value="${basedir}/resources"/> <property name="dir.target" value="${basedir}/target"/> <property name="xjc.exec" value="${env.JAVA_HOME}/bin/xjc"/> <target name="clean" description="clean all generated folders"> <delete dir="${dir.target}"/> </target> <target name="generate-source" depends="clean" description="generate sources from the schema XSD"> <echo>Generate sources</echo> <mkdir dir="${dir.target}"/> <exec executable="${xjc.exec}"> <arg line="-nv"/> <arg line="-extension"/> <arg line="-d "${dir.target}""/> <arg line="${dir.resources}/'mobile phone.xsd'"/> </exec> </target> </project>Chú ý biến môi trường (environment variable) JAVA_HOME phải được định nghĩa.
Ta tạo thư mục dự án (project) trong Eclipse có cấu trúc sau:
Nội dung mã trong tập tin JaxbTest.java
package xml.test; import generated.MobilePhones; import generated.MobilePhones.MobilePhone; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.junit.Assert; import org.junit.Test; public class JaxbTest { private static Runtime runtime = Runtime.getRuntime(); @Test public void readWriteXmlWithJaxb() { try { long startTime = System.currentTimeMillis(); System.out.println("Before reading file : " + (runtime.totalMemory() - runtime.freeMemory()) + " bytes" ); JAXBContext jc = JAXBContext.newInstance(MobilePhones.class); Unmarshaller um = jc.createUnmarshaller(); File f = new File("resources/mobile phone.xml"); MobilePhones root = (MobilePhones) um.unmarshal(f); MobilePhone phone = root.getMobilePhone().get(0); Assert.assertEquals("smartphone", phone.getCategory()); MobilePhone phoneToAdd = new MobilePhone(); phoneToAdd.setCategory("smartphone"); phoneToAdd.setDescription("smartphone of HTC"); phoneToAdd.setManufacturer("HTC"); phoneToAdd.setName("HTC Desire"); phoneToAdd.setOs("Android"); root.getMobilePhone().add(phoneToAdd); System.out.println("After generating objects : " + (runtime.totalMemory() - runtime.freeMemory()) + " bytes" ); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); OutputStream os = new FileOutputStream("resources/jaxbOutput.xml"); m.marshal(root, os); long endTime = System.currentTimeMillis(); System.out.println("After writing to XML file : " + (runtime.totalMemory() - runtime.freeMemory()) + " bytes" ); System.out.println("Execution time : " +(endTime - startTime) + " mili seconds"); } catch (JAXBException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
Giải thích mã:
- Đầu tiên
Unmarshaller
được dùng để đọc và chuyển phồng tập tin "mobile phone.xml" vào đối tượng MobilePhones root
.- Lấy đối tượng
MobilePhone
đầu tiên, phone. - Tiếp theo, kiểm tra giá trị thành phần
category
của phone
đúng là "smartphone".- Tạo một đối tượng
MobilePhone phoneToAdd
và thêm nó vào root
.- Chuyển xẹp nội dung toàn bộ
root
vừa thay đổi và ghi nó vào tập tin "jaxbOutput.xml" dùng Marshaller
.Nhận xét:
- JAXB cho phép ta đọc, chỉnh sửa hay thêm nội dung trong quá trình đọc và sau cùng lưu lại nội dung vừa thay đổi.
- JAXB tương tự như DOM và JDOM đọc toàn bộ nội dung tập tin xml và lưu nó trong bộ nhớ. Do đó, dùng JAXB tốn nhiều bộ nhớ đặc biệt khi đọc những tập tin dung lượng lớn.
- Khác với DOM và JDOM, ta không thể tự động thêm vào tập tin XML những thành phần hay thuộc tính không đuợc định nghĩa trong lược đồ XML. Muốn thêm chúng, ta phải thêm vào tập tin XSD, và tái phát sinh mã java.
Không có nhận xét nào:
Đăng nhận xét