OXM簡(jiǎn)介
我們都知道對(duì)象關(guān)系映射(ORM),用來將Java對(duì)象和關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行映射。Spring也提供了一套類似的映射機(jī)制,用來將Java對(duì)象和XML文件進(jìn)行映射。這就是Spring的對(duì)象XML映射功能,有時(shí)候也成為XML的序列化和反序列化。
這套功能的最基本的兩個(gè)接口就是org.springframework.oxm.Marshaller和org.springframework.oxm.Unmarshaller,前者用于將Java對(duì)象轉(zhuǎn)換成XML文件,后者用于將XML文件轉(zhuǎn)換成Java對(duì)象。
Marshaller接口如下,它有一個(gè)marshal方法,包含要序列化的對(duì)象,結(jié)果會(huì)返回到Result參數(shù)上。Result也是一個(gè)接口,相應(yīng)的有幾個(gè)實(shí)現(xiàn)DOMResult、SAXResult和StreamResult,代表幾種不同的XML技術(shù)。
public interface Marshaller {
void marshal(Object graph, Result result) throws XmlMappingException, IOException;
}
Unmarshaller接口也是類似的,它有一個(gè)unmarshal方法,將傳入的Source反序列化Java對(duì)象。相應(yīng)的Source也有三個(gè)實(shí)現(xiàn)DOMSource、SAXSource和StreamSource,代表這幾種技術(shù)。
public interface Unmarshaller {
Object unmarshal(Source source) throws XmlMappingException, IOException;
}
基本使用
要使用Spring的OXM功能,需要添加它的依賴。如果使用Gradle,添加下面的依賴項(xiàng)。
compile group: 'org.springframework', name: 'spring-oxm', version: '4.3.6.RELEASE'
Spring提供了幾個(gè)Marshaller和Unmarshaller接口的實(shí)現(xiàn),用來進(jìn)行各種轉(zhuǎn)換操作。我們來使用最簡(jiǎn)單的一個(gè)轉(zhuǎn)換器CastorMarshaller,它同時(shí)實(shí)現(xiàn)了Marshaller和Unmarshaller接口,因此我們可以使用它同時(shí)進(jìn)行序列化和反序列化。同時(shí)它不需要其他額外配置。在配置文件中,聲明如下一個(gè)Bean。
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
我們來定義一個(gè)實(shí)體類來進(jìn)行XML序列化和反序列化,方法已省略,只列出字段。
public class User {
private int id;
private String name;
private int age;
}
然后我們使用一個(gè)方法來測(cè)試
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);
//直接輸出到標(biāo)準(zhǔn)輸出流
Result result = new StreamResult(System.out);
marshaller.marshal(user, result);
System.out.println();
}
}
我們可以在控制臺(tái)上得到類似下面的輸出。我們可以看到CastorMarshaller默認(rèn)情況下會(huì)將簡(jiǎn)單類型處理為屬性,引用類型處理為子元素。
<?xml version="1.0" encoding="UTF-8"?>
<user age="24" id="1"><name>yitian</name></user>
各種序列化器
下面來介紹一下Spring實(shí)現(xiàn)的一些XML序列化器和反序列化器
JAXB
JAXB全稱是Java Architecture for XML Binding,為XML表和Java對(duì)象之間提供了快速而簡(jiǎn)單的綁定。org.springframework.oxm.jaxb.Jaxb2Marshaller同時(shí)實(shí)現(xiàn)了Marshaller和Unmarshaller,所以我們只需要配置一個(gè)Jaxb2Marshaller即可。使用JAXB,我們需要設(shè)置其classesToBeBound屬性指定要綁定哪些類,還可以設(shè)置schema屬性提供XML的驗(yàn)證。JAXB的詳細(xì)使用方法請(qǐng)參見其文檔。
<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命名空間簡(jiǎn)化配置。
<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
Castor是一個(gè)開源的XML綁定框架。詳細(xì)使用方法請(qǐng)參見其文檔。該類庫(kù)是一個(gè)第三方類庫(kù),所以為了使用它還需要引用其類庫(kù)。CastorMarshaller同時(shí)實(shí)現(xiàn)了Marshaller和Unmarshaller。
默認(rèn)情況下不需要配置即可使用。如果需要配置XML綁定,我們可以添加一個(gè)綁定文件,綁定文件如何編寫參見Castor XML Mapping。
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
<property name="mappingLocation" value="classpath:mapping.xml" />
</bean>
</beans>
當(dāng)然也可以使用oxm命名空間簡(jiǎn)化。
<oxm:castor-marshaller id="marshaller" mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/>
XMLBeans(已過時(shí))
XMLBeans也是一個(gè)XML綁定工具,但是它的綁定功能需要Java類繼承XmlObject基類。
XmlBeansMarshaller同時(shí)實(shí)現(xiàn)了Marshaller和Unmarshaller。我們需要添加如下的Bean配置。
<bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" />
或者使用oxm命名空間。
<oxm:xmlbeans-marshaller id="marshaller"/>
由于XMLBeans項(xiàng)目已過時(shí),因此Spring相應(yīng)的XMLBeans類也過時(shí)了。
JiBX
JiBX.也是一個(gè)XML映射類庫(kù),它提供和JDO的對(duì)象關(guān)系映射類似的功能。
JibxMarshaller同時(shí)實(shí)現(xiàn)了Marshaller和Unmarshaller。
它的Bean配置文件如下。我們使用targetClass屬性向其添加要映射的類。
<bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass">foo.Bar</property>
</bean>
或者使用oxm命名空間簡(jiǎn)化。
<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>
JibxMarshaller設(shè)計(jì)為只為一個(gè)類進(jìn)行序列化和反序列化。因此如果要序列化多個(gè)類,就需要配置多個(gè)JibxMarshaller。
XStream
XStream是一個(gè)簡(jiǎn)單的XML序列化庫(kù)。
默認(rèn)情況下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可以反序列化匿名類,可能會(huì)造成安全隱患。所以最好不要使用XStream來反序列化外部加載的XML(例如網(wǎng)絡(luò)上的XML)。我們還可以使用supportedClasses屬性注冊(cè)類,這樣會(huì)確保我們只反序列化注冊(cè)的類。
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="supportedClasses" value="foo.Bar"/>
...
</bean>
另外需要注意XStream只是一個(gè)XML序列化庫(kù),而不是數(shù)據(jù)綁定庫(kù)。也就是說它的功能不如前面幾個(gè)庫(kù)完善,有些命名空間不支持。因此你無法用XStream來完成類似Web服務(wù)的功能。