OXM 介紹
OXM全名為Objec XML Mapping,主要的功能為 Java Bean 與 XML 之間的轉換工作。Castor 的優點為不需要定義映射檔,比起JAXB更為一項輕量級的應用。 在OXM中有兩項重要的名詞 marshal 與 unmarshal,將 Object 轉換為 XML 的動作稱為 marshal,反之稱為 unmarshal,如此的習慣也在JAXB中出現。 此外,在我實驗的過程中發現 Castor 為採用反射的方式建立物件,因此擁有一項優點為可以任意 unmarshal 物件,即使與原先 marshal 的物件為不同的 Class,增加了許多設計的彈性。
Castor官方網站 http://www.castor.org/
Castor 實作 - Castor 需要的套件
- castor-1.3-core.jar
- castor-1.3-xml.jar
- castor-1.3-xml-schema.jar
下載網址 http://www.castor.org/download.html#Castor 此外 Castor 在執行的時候也需要:
- log4j-1.2.15.jar
- commons-logging-1.1.1.jar
這兩包套件可在Apache網站取得
Marshal 實作
在這個章節中我們測試在物件中存放參數與子物件進行OXM:
- 設計一個 Model
private String title; private int num; private Integer sort; private List<SubModel> list; private Hashtable<String,SubModel> table;
- 設計一個SubModel
private String name;
- Marshal 轉換程式 Object2XML.java
import java.io.StringWriter; import java.util.ArrayList; import java.util.Hashtable; import org.exolab.castor.xml.Marshaller; public class Object2XML { public static void main(String[] args) { Model model = new Model(); model.setTitle("Master MOdel"); model.setNum(99); model.setSort(10); model.setList(new ArrayList<SubModel>()); model.setTable(new Hashtable<String,SubModel>()); //加入兩組SubModel到List SubModel subModel1 = new SubModel(); subModel1.setName("Sub Model 1"); model.getList().add(subModel1); SubModel subModel2 = new SubModel(); subModel2.setName("Sub Model 2"); model.getList().add(subModel2); //加入SubModel到HashTable SubModel subModel3 = new SubModel(); subModel3.setName("Sub Model 3"); model.getTable().put("Sub Model 3", subModel3); //轉換為XML StringWriter stringWriter = new StringWriter(); try { Marshaller.marshal(model, stringWriter); } catch (Exception e) { e.printStackTrace(); } //顯示XML System.out.println(stringWriter.toString()); } }
- Unmarshal 轉換程式 XML2Object.java
import java.io.StringReader; import java.util.Enumeration; import org.exolab.castor.xml.Unmarshaller; public class XML2Object { public static void main(String[] args) { String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><model num=\"99\"><sort>10</sort><table xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:java=\"http://java.sun.com\" xsi:type=\"java:org.exolab.castor.mapping.MapItem\"><key xsi:type=\"java:java.lang.String\">Sub Model 3</key><value xsi:type=\"java:SubModel\"><name>Sub Model 3</name></value></table><list xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:java=\"http://java.sun.com\" xsi:type=\"java:SubModel\"><name>Sub Model 1</name></list><list xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:java=\"http://java.sun.com\" xsi:type=\"java:SubModel\"><name>Sub Model 2</name></list><title>Master MOdel</title></model>"; //轉換JavaBean Model model = null; try { StringReader stringReader = new StringReader(xml); model = (Model)Unmarshaller.unmarshal(Model.class, stringReader); } catch (Exception e) { e.printStackTrace(); } //顯示內容 System.out.println("Title:"+model.getTitle()); System.out.println("Num:"+model.getNum()); System.out.println("Sort:"+model.getSort()); for (SubModel subModel : model.getList()) { System.out.println("[List] SubModel Name:"+subModel.getName()); } Enumeration<SubModel> enumeration = model.getTable().elements(); while( enumeration.hasMoreElements() ){ SubModel subModel = enumeration.nextElement(); System.out.println("[Table] SubModel Name:"+subModel.getName()); } } }
執行結果
- Object2XML.java
< ?xml version="1.0" encoding="UTF-8" ?>
- XML2Object.java
log4j:WARN No appenders could be found for logger (org.castor.core.util.AbstractProperties). log4j:WARN Please initialize the log4j system properly. Title:Master MOdel Num:99 Sort:10 [List] SubModel Name:Sub Model 1 [List] SubModel Name:Sub Model 2 [Table] SubModel Name:Sub Model 3
結論
Castor 在使用上確實比 JAXB 來的簡易,假如搭配 Java Class Loader 更能夠發揮自動化的功用,在 OXM 扮演了很重要的角色,也符合 XDNA Framework 精簡快速的精神。