使用物件-XML 對應器編組 XML
簡介
本章節描述 Spring 的物件-XML 對應支援。物件-XML 對應(簡稱 O-X 對應)是將 XML 文件轉換為物件以及從物件轉換為 XML 文件的動作。此轉換過程也稱為 XML 編組或 XML 序列化。本章節交替使用這些術語。
在 O-X 對應領域中,marshaller 負責將物件(圖形)序列化為 XML。以類似的方式,unmarshaller 將 XML 反序列化為物件圖形。此 XML 可以採用 DOM 文件、輸入或輸出流或 SAX 處理常式的形式。
將 Spring 用於您的 O/X 對應需求的一些優點包括:
易於設定
Spring 的 bean 工廠可以輕鬆設定 marshaller,而無需建構 JAXB context、JiBX binding factory 等。您可以像設定應用程式 Context 中的任何其他 bean 一樣設定 marshaller。此外,XML 命名空間型設定適用於許多 marshaller,使設定更加簡單。
一致的介面
Spring 的 O-X 對應透過兩個全域介面運作:Marshaller
和 Unmarshaller
。這些抽象化讓您可以相對輕鬆地切換 O-X 對應框架,而對執行編組的類別幾乎不需要或完全不需要變更。此方法還有一個額外的好處,就是可以以非侵入式的方式執行混合搭配方法 (例如,使用 JAXB 執行某些編組,而使用 XStream 執行某些編組) 的 XML 編組,讓您可以使用每種技術的優勢。
Marshaller
和 Unmarshaller
如簡介中所述,marshaller 將物件序列化為 XML,而 unmarshaller 將 XML 流反序列化為物件。本節描述用於此目的的兩個 Spring 介面。
了解 Marshaller
Spring 將所有編組操作抽象化在 org.springframework.oxm.Marshaller
介面之後,其主要方法如下:
public interface Marshaller {
/**
* Marshal the object graph with the given root into the provided Result.
*/
void marshal(Object graph, Result result) throws XmlMappingException, IOException;
}
Marshaller
介面有一個主要方法,該方法將給定的物件編組到給定的 javax.xml.transform.Result
。結果是一個標記介面,基本上代表 XML 輸出抽象化。具體實作包裝各種 XML 表示法,如下表所示:
Result 實作 | 包裝 XML 表示法 |
---|---|
|
|
|
|
|
|
雖然 marshal() 方法接受純物件作為其第一個參數,但大多數 Marshaller 實作無法處理任意物件。相反,物件類別必須在對應檔案中對應、使用註解標記、向 marshaller 註冊或具有通用基底類別。請參閱本章後面的章節,以判斷您的 O-X 技術如何管理此問題。 |
了解 Unmarshaller
與 Marshaller
類似,我們有 org.springframework.oxm.Unmarshaller
介面,以下清單顯示了該介面:
public interface Unmarshaller {
/**
* Unmarshal the given provided Source into an object graph.
*/
Object unmarshal(Source source) throws XmlMappingException, IOException;
}
此介面也有一個方法,該方法從給定的 javax.xml.transform.Source
(XML 輸入抽象化) 讀取,並傳回讀取的物件。與 Result
一樣,Source
是一個標記介面,具有三個具體實作。每個實作都包裝了不同的 XML 表示法,如下表所示:
Source 實作 | 包裝 XML 表示法 |
---|---|
|
|
|
|
|
|
即使有兩個單獨的編組介面 (Marshaller
和 Unmarshaller
),Spring-WS 中的所有實作都在一個類別中實作了這兩個介面。這表示您可以連接一個 marshaller 類別,並在您的 applicationContext.xml
中將其同時稱為 marshaller 和 unmarshaller。
使用 Marshaller
和 Unmarshaller
您可以將 Spring 的 OXM 用於各種情況。在以下範例中,我們使用它將 Spring 管理的應用程式的設定編組為 XML 檔案。在以下範例中,我們使用簡單的 JavaBean 來表示設定:
-
Java
-
Kotlin
public class Settings {
private boolean fooEnabled;
public boolean isFooEnabled() {
return fooEnabled;
}
public void setFooEnabled(boolean fooEnabled) {
this.fooEnabled = fooEnabled;
}
}
class Settings {
var isFooEnabled: Boolean = false
}
應用程式類別使用此 bean 來儲存其設定。除了 main 方法之外,該類別還有兩個方法:saveSettings()
將設定 bean 儲存到名為 settings.xml
的檔案中,而 loadSettings()
再次載入這些設定。以下 main()
方法建構 Spring 應用程式 Context 並呼叫這兩個方法:
-
Java
-
Kotlin
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
public class Application {
private static final String FILE_NAME = "settings.xml";
private Settings settings = new Settings();
private Marshaller marshaller;
private Unmarshaller unmarshaller;
public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}
public void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}
public void saveSettings() throws IOException {
try (FileOutputStream os = new FileOutputStream(FILE_NAME)) {
this.marshaller.marshal(settings, new StreamResult(os));
}
}
public void loadSettings() throws IOException {
try (FileInputStream is = new FileInputStream(FILE_NAME)) {
this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is));
}
}
public static void main(String[] args) throws IOException {
ApplicationContext appContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
Application application = (Application) appContext.getBean("application");
application.saveSettings();
application.loadSettings();
}
}
class Application {
lateinit var marshaller: Marshaller
lateinit var unmarshaller: Unmarshaller
fun saveSettings() {
FileOutputStream(FILE_NAME).use { outputStream -> marshaller.marshal(settings, StreamResult(outputStream)) }
}
fun loadSettings() {
FileInputStream(FILE_NAME).use { inputStream -> settings = unmarshaller.unmarshal(StreamSource(inputStream)) as Settings }
}
}
private const val FILE_NAME = "settings.xml"
fun main(args: Array<String>) {
val appContext = ClassPathXmlApplicationContext("applicationContext.xml")
val application = appContext.getBean("application") as Application
application.saveSettings()
application.loadSettings()
}
Application
需要設定 marshaller
和 unmarshaller
屬性。我們可以透過使用以下 applicationContext.xml
來執行此操作:
<beans>
<bean id="application" class="Application">
<property name="marshaller" ref="xstreamMarshaller" />
<property name="unmarshaller" ref="xstreamMarshaller" />
</bean>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
</beans>
此應用程式 Context 使用 XStream,但我們可以使用本章稍後描述的任何其他 marshaller 實例。請注意,預設情況下,XStream 不需要任何其他設定,因此 bean 定義相當簡單。另請注意,XStreamMarshaller
同時實作 Marshaller
和 Unmarshaller
,因此我們可以在應用程式的 marshaller
和 unmarshaller
屬性中同時參考 xstreamMarshaller
bean。
此範例應用程式產生以下 settings.xml
檔案:
<?xml version="1.0" encoding="UTF-8"?>
<settings foo-enabled="false"/>
XML 設定命名空間
您可以透過使用 OXM 命名空間中的標籤,以更簡潔的方式設定 marshaller。若要使這些標籤可用,您必須先在 XML 設定檔案的前言中參考適當的 schema。以下範例示範了如何執行此操作:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oxm="http://www.springframework.org/schema/oxm" (1)
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/oxm
https://www.springframework.org/schema/oxm/spring-oxm.xsd"> (2)
1 | 參考 oxm schema。 |
2 | 指定 oxm schema 位置。 |
schema 使以下元素可用:
每個標籤都在其各自的 marshaller 區段中說明。但是,作為範例,JAXB2 marshaller 的設定可能類似於以下內容:
<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>
JAXB
JAXB binding compiler 將 W3C XML Schema 轉換為一個或多個 Java 類別、一個 jaxb.properties
檔案,以及可能的一些資源檔案。JAXB 也提供了一種從註解的 Java 類別產生 schema 的方法。
Spring 支援 JAXB 2.0 API 作為 XML 編組策略,遵循Marshaller
和 Unmarshaller
中描述的 Marshaller
和 Unmarshaller
介面。對應的整合類別位於 org.springframework.oxm.jaxb
套件中。
使用 Jaxb2Marshaller
Jaxb2Marshaller
類別同時實作了 Spring 的 Marshaller
和 Unmarshaller
介面。它需要 Context 路徑才能運作。您可以透過設定 contextPath
屬性來設定 Context 路徑。Context 路徑是以冒號分隔的 Java 套件名稱列表,其中包含 schema 衍生的類別。它還提供了一個 classesToBeBound
屬性,可讓您設定 marshaller 支援的類別陣列。透過為 bean 指定一個或多個 schema 資源來執行 Schema 驗證,如下列範例所示:
<beans>
<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>org.springframework.oxm.jaxb.Flight</value>
<value>org.springframework.oxm.jaxb.Flights</value>
</list>
</property>
<property name="schema" value="classpath:org/springframework/oxm/schema.xsd"/>
</bean>
...
</beans>
XML 設定命名空間
jaxb2-marshaller
元素設定 org.springframework.oxm.jaxb.Jaxb2Marshaller
,如下列範例所示:
<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>
或者,您可以使用 class-to-be-bound
子元素來提供要繫結到 marshaller 的類別列表:
<oxm:jaxb2-marshaller id="marshaller">
<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Airport"/>
<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Flight"/>
...
</oxm:jaxb2-marshaller>
下表描述了可用的屬性:
屬性 | 描述 | 必要 |
---|---|---|
|
marshaller 的 ID |
否 |
|
JAXB Context 路徑 |
否 |
JiBX
JiBX 框架提供了一種類似於 Hibernate 為 ORM 提供的解決方案:繫結定義定義了 Java 物件如何轉換為 XML 或從 XML 轉換的規則。在準備繫結並編譯類別之後,JiBX binding compiler 會增強類別檔案,並新增程式碼以處理類別實例從 XML 或轉換為 XML 的轉換。
如需 JiBX 的詳細資訊,請參閱 JiBX 網站。Spring 整合類別位於 org.springframework.oxm.jibx
套件中。
使用 JibxMarshaller
JibxMarshaller
類別同時實作了 Marshaller
和 Unmarshaller
介面。若要運作,它需要編組中類別的名稱,您可以使用 targetClass
屬性來設定該名稱。或者,您可以透過設定 bindingName
屬性來設定繫結名稱。在以下範例中,我們繫結 Flights
類別:
<beans>
<bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass">org.springframework.oxm.jibx.Flights</property>
</bean>
...
</beans>
JibxMarshaller
是為單一類別設定的。如果您想要編組多個類別,則必須設定多個具有不同 targetClass
屬性值的 JibxMarshaller
實例。
XML 設定命名空間
jibx-marshaller
標籤設定 org.springframework.oxm.jibx.JibxMarshaller
,如下列範例所示:
<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>
下表描述了可用的屬性:
屬性 | 描述 | 必要 |
---|---|---|
|
marshaller 的 ID |
否 |
|
此 marshaller 的目標類別 |
是 |
|
此 marshaller 使用的繫結名稱 |
否 |
XStream
XStream 是一個簡單的程式庫,可將物件序列化為 XML 並再次返回。它不需要任何對應,並產生清晰的 XML。
如需 XStream 的詳細資訊,請參閱 XStream 網站。Spring 整合類別位於 org.springframework.oxm.xstream
套件中。
使用 XStreamMarshaller
XStreamMarshaller
不需要任何設定,並且可以直接在應用程式 Context 中設定。為了進一步自訂 XML,您可以設定別名 Map,該 Map 由對應到類別的字串別名組成,如下列範例所示:
<beans>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<props>
<prop key="Flight">org.springframework.oxm.xstream.Flight</prop>
</props>
</property>
</bean>
...
</beans>
預設情況下,XStream 允許反編組任意類別,這可能會導致不安全的 Java 序列化效果。因此,我們不建議使用 如果您選擇使用
這樣做可確保只有註冊的類別才有資格進行反編組。 此外,您可以註冊自訂轉換器,以確保只有您支援的類別可以反編組。除了明確支援應支援的網域類別的轉換器之外,您可能還想要將 |
請注意,XStream 是一個 XML 序列化程式庫,而不是資料繫結程式庫。因此,它的命名空間支援有限。因此,它不太適合在 Web 服務中使用。 |