OXM簡介
我們都知道對象關系映射(ORM),用來将Java對象和關系型資料庫的資料進行映射。Spring也提供了一套類似的映射機制,用來将Java對象和XML檔案進行映射。這就是Spring的對象XML映射功能,有時候也成為XML的序列化和反序列化。
這套功能的最基本的兩個接口就是
org.springframework.oxm.Marshaller
和
org.springframework.oxm.Unmarshaller
,前者用于将Java對象轉換成XML檔案,後者用于将XML檔案轉換成Java對象。
Marshaller接口如下,它有一個marshal方法,包含要序列化的對象,結果會傳回到Result參數上。Result也是一個接口,相應的有幾個實作DOMResult、SAXResult和StreamResult,代表幾種不同的XML技術。
public interface Marshaller {
void marshal(Object graph, Result result) throws XmlMappingException, IOException;
}
Unmarshaller
接口也是類似的,它有一個unmarshal方法,将傳入的Source反序列化Java對象。相應的Source也有三個實作DOMSource、SAXSource和StreamSource,代表這幾種技術。
public interface Unmarshaller {
Object unmarshal(Source source) throws XmlMappingException, IOException;
}
基本使用
要使用Spring的OXM功能,需要添加它的依賴。如果使用Gradle,添加下面的依賴項。
compile group: 'org.springframework', name: 'spring-oxm', version: '4.3.6.RELEASE'
Spring提供了幾個Marshaller和Unmarshaller接口的實作,用來進行各種轉換操作。我們來使用最簡單的一個轉換器CastorMarshaller,它同時實作了Marshaller和Unmarshaller接口,是以我們可以使用它同時進行序列化和反序列化。同時它不需要其他額外配置。在配置檔案中,聲明如下一個Bean。
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
我們來定義一個實體類來進行XML序列化和反序列化,方法已省略,隻列出字段。
public class User {
private int id;
private String name;
private int age;
}
然後我們使用一個方法來測試
public class OXMTest {
private static ApplicationContext context;
private static User user;
@BeforeClass
public static void init() {
context = new ClassPathXmlApplicationContext("classpath:oxm.xml");
user = new User();
user.setName("yitian");
user.setAge(24);
user.setId(1);
}
@Test
public void test() throws IOException {
Marshaller marshaller = context.getBean("castorMarshaller", CastorMarshaller.class);
Unmarshaller unmarshaller = context.getBean("castorMarshaller", CastorMarshaller.class);
//直接輸出到标準輸出流
Result result = new StreamResult(System.out);
marshaller.marshal(user, result);
System.out.println();
}
}
我們可以在控制台上得到類似下面的輸出。我們可以看到CastorMarshaller預設情況下會将簡單類型處理為屬性,引用類型處理為子元素。
<?xml version="1.0" encoding="UTF-8"?>
<user age="24" id="1"><name>yitian</name></user>
各種序列化器
下面來介紹一下Spring實作的一些XML序列化器和反序列化器
JAXB
全稱是Java Architecture for XML Binding,為XML表和Java對象之間提供了快速而簡單的綁定。
org.springframework.oxm.jaxb.Jaxb2Marshaller
同時實作了Marshaller和Unmarshaller,是以我們隻需要配置一個Jaxb2Marshaller即可。使用JAXB,我們需要設定其classesToBeBound屬性指定要綁定哪些類,還可以設定schema屬性提供XML的驗證。JAXB的詳細使用方法請參見其文檔。
<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>foo.bar.Bean1</value>
<value>foo.bar.Bean2</value>
</list>
</property>
<property name="schema" value="classpath:foo.xsd"/>
</bean>
也可以使用oxm命名空間簡化配置。
<oxm:jaxb2-marshaller id="marshaller">
<oxm:class-to-be-bound name="foo.bar.Bean1"/>
<oxm:class-to-be-bound name="foo.bar.Bean2"/>
...
</oxm:jaxb2-marshaller>
Castor
是一個開源的XML綁定架構。詳細使用方法請參見其文檔。該類庫是一個第三方類庫,是以為了使用它還需要引用其類庫。CastorMarshaller同時實作了Marshaller和Unmarshaller。
預設情況下不需要配置即可使用。如果需要配置XML綁定,我們可以添加一個綁定檔案,綁定檔案如何編寫參見
Castor XML Mapping。
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
<property name="mappingLocation" value="classpath:mapping.xml" />
</bean>
</beans>
當然也可以使用oxm命名空間簡化。
<oxm:castor-marshaller id="marshaller" mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/>
XMLBeans(已過時)
XMLBeans也是一個XML綁定工具,但是它的綁定功能需要Java類繼承XmlObject基類。
XmlBeansMarshaller同時實作了Marshaller和Unmarshaller。我們需要添加如下的Bean配置。
<bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" />
或者使用oxm命名空間。
<oxm:xmlbeans-marshaller id="marshaller"/>
由于XMLBeans項目已過時,是以Spring相應的XMLBeans類也過時了。
JiBX
.也是一個XML映射類庫,它提供和JDO的對象關系映射類似的功能。
JibxMarshaller同時實作了Marshaller和Unmarshaller。
它的Bean配置檔案如下。我們使用targetClass屬性向其添加要映射的類。
<bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass">foo.Bar</property>
</bean>
或者使用oxm命名空間簡化。
<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>
JibxMarshaller設計為隻為一個類進行序列化和反序列化。是以如果要序列化多個類,就需要配置多個JibxMarshaller。
XStream
是一個簡單的XML序列化庫。
預設情況下XStream不需要任何配置即可使用。如果需要配置的話,可以使用aliases屬性自定義生成的XML檔案。
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<props>
<prop key="bar">foo.Bar</prop>
</props>
</property>
</bean>
XStream可以反序列化匿名類,可能會造成安全隐患。是以最好不要使用XStream來反序列化外部加載的XML(例如網絡上的XML)。我們還可以使用supportedClasses屬性注冊類,這樣會確定我們隻反序列化注冊的類。
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="supportedClasses" value="foo.Bar"/>
...
</bean>
另外需要注意XStream隻是一個XML序列化庫,而不是資料綁定庫。也就是說它的功能不如前面幾個庫完善,有些命名空間不支援。是以你無法用XStream來完成類似Web服務的功能。