本章介绍了Spring的Object-XML Mapping支持。对象XML映射(简称O-X映射)是将XML文档与对象进行相互转换的动作。此转换过程也称为XML编组或XML序列化。本章可以互换使用这些术语。
在O-X映射领域中,marshaller负责将对象(图形)序列化为XML。以类似的方式,unmarshaller将XML反序列化为对象图。该XML可以采用DOM文档,输入或输出流或SAX处理程序的形式。
使用Spring满足O / X映射需求的一些好处是:
使用Spring的bean工厂,可以轻松配置编组器,而无需构造JAXB上下文,JiBX绑定工厂等。您可以像在应用程序上下文中配置任何其他bean一样配置编组器。此外,许多编组人员都可以使用基于XML名称空间的配置,从而使配置更加简单。
Spring的O-X映射通过两个全局接口运行:Marshaller和Unmarshaller。这些抽象使您可以相对轻松地切换O-X映射框架,而进行编组的类几乎不需要更改。这种方法还有一个好处,就是可以以非介入方式使用混合匹配方法(例如,一些使用JAXB进行的编组和某些由Castor进行的编组)进行XML编组,从而让您充分利用每种方法的优势技术。
Spring提供了从底层O-X映射工具到XmlMappingException作为根异常的异常层次转换。这些运行时异常包装原始异常,因此不会丢失任何信息。
如引言中所述,封送器将对象序列化为XML,解组器将XML流反序列化为对象。 本节描述了用于此目的的两个Spring接口。
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表示形式:
即使有两个单独的编组接口(Marshaller和Unmarshaller),Spring-WS中的所有实现都在一个类中实现。 这意味着您可以连接一个编组类,并在applicationContext.xml中将其称为编组和解组。
Spring使用XmlMappingException作为根异常,将基础O-X映射工具中的异常转换为它自己的异常层次结构。 这些运行时异常包装了原始异常,因此不会丢失任何信息。
此外,即使基础的O-X映射工具没有这样做,MarshallingFailureException和UnmarshallingFailureException也会在编组和解组操作之间进行区分。
O-X映射异常层次结构如下图所示:
您可以在多种情况下使用Spring的OXM。 在下面的示例中,我们使用它来将Spring托管应用程序的设置作为XML文件进行编组。 在下面的示例中,我们使用一个简单的JavaBean来表示设置:
public class Settings { private boolean fooEnabled; public boolean isFooEnabled() { return fooEnabled; } public void setFooEnabled(boolean fooEnabled) { this.fooEnabled = fooEnabled; } }
应用程序类使用此bean存储其设置。 除了主要方法之外,该类还有两个方法:saveSettings()将settings Bean保存到名为settings.xml的文件中,loadSettings()再次加载这些设置。 下面的main()方法构造一个Spring应用程序上下文并调用这两个方法:
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(); } }
该应用程序需要同时设置封送程序和取消封送程序属性。 我们可以使用以下applicationContext.xml来做到这一点:
<beans> <bean id="application" class="Application"> <property name="marshaller" ref="castorMarshaller" /> <property name="unmarshaller" ref="castorMarshaller" /> </bean> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/> </beans>
该应用程序上下文使用Castor,但是我们可以使用本章后面介绍的任何其他编组实例。 请注意,默认情况下,Castor不需要任何进一步的配置,因此Bean的定义非常简单。 还要注意,CastorMarshaller同时实现了Marshaller和Unmarshaller,因此我们可以在应用程序的marshaller和unmarshaller属性中引用castorMarshaller bean。
该示例应用程序生成以下settings.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <settings foo-enabled="false"/>
您可以使用OXM名称空间中的标签来更简洁地配置编组器。 要使这些标签可用,您必须首先在XML配置文件的序言中引用适当的架构。 以下示例显示了如何执行此操作:
<?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" 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">
当前,该模式使以下元素可用:
jaxb2-marshaller
jibx-marshaller
castor-marshaller
每个标签均在其各自的编组部分中进行了说明。 但是,作为示例,JAXB2编组器的配置可能类似于以下内容:
<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>
JAXB绑定编译器将W3C XML Schema转换为一个或多个Java类,一个jaxb.properties文件以及可能的一些资源文件。 JAXB还提供了一种从带注解的Java类生成模式的方法。
遵循Marshaller和Unmarshaller中描述的Marshaller和Unmarshaller接口,Spring支持JAXB 2.0 API作为XML编组策略。相应的集成类位于org.springframework.oxm.jaxb包中。
Jaxb2Marshaller类实现了Spring的Marshaller和Unmarshaller接口。它需要上下文路径才能运行。您可以通过设置contextPath属性来设置上下文路径。上下文路径是冒号分隔的Java程序包名称的列表,其中包含模式派生的类。它还提供了classesToBeBound属性,该属性使您可以设置编组支持的类的数组。通过向Bean指定一个或多个模式资源来执行模式验证,如以下示例所示:
<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"> <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>
下表描述了可用的属性:
Castor XML映射是一个开源XML绑定框架。 它使您可以将Java对象模型中包含的数据与XML文档进行相互转换。 默认情况下,它不需要任何进一步的配置,尽管您可以使用映射文件来更好地控制Castor的行为。
有关Castor的更多信息,请参见Castor网站。 Spring集成类位于org.springframework.oxm.castor包中。
与JAXB一样,CastorMarshaller也实现Marshaller和Unmarshaller接口。 可以按以下方式进行连接:
<beans> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" /> ... </beans>
尽管可以依赖Castor的默认编组行为,但可能需要对其进行更多控制。 您可以通过使用Castor映射文件来获得更多控制。 有关更多信息,请参见Castor XML映射。
您可以通过使用mappingLocation资源属性来设置映射,在以下示例中使用类路径资源来指示:
<beans> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" > <property name="mappingLocation" value="classpath:mapping.xml" /> </bean> </beans>
castor-marshaller标记配置org.springframework.oxm.castor.CastorMarshaller,如以下示例所示:
<oxm:castor-marshaller id="marshaller" mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/>
您可以通过两种方式配置marshaller实例:通过指定映射文件的位置(通过mapping-location属性)或通过标识Java POJO(通过target-class或target-package属性)来确定存在其对应XML的Java POJO。 描述符类。 后一种方法通常与从XML模式生成XML代码结合使用。
JiBX框架提供了与Hibernate为ORM提供的解决方案类似的解决方案:绑定定义定义了Java对象如何与XML相互转换的规则。 在准备好绑定并编译了类之后,JiBX绑定编译器将增强类文件并添加代码以处理将类的实例从XML转换为XML的过程。
有关JiBX的更多信息,请参见JiBX网站。 Spring集成类位于org.springframework.oxm.jibx包中。
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实例。
jibx-marshaller标记配置org.springframework.oxm.jibx.JibxMarshaller,如以下示例所示:
<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>
XStream是一个简单的库,用于将对象序列化为XML并再次返回。 它不需要任何映射并生成干净的XML。
有关XStream的更多信息,请参见XStream网站。 Spring集成类位于org.springframework.oxm.xstream包中。
XStreamMarshaller不需要任何配置,可以直接在应用程序上下文中进行配置。 要进一步自定义XML,可以设置一个别名映射,该映射由映射到类的字符串别名组成,如以下示例所示:
<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序列化效果。因此,我们不建议使用XStreamMarshaller从外部源(即Web)解组XML,因为这可能会导致安全漏洞。 如果选择使用XStreamMarshaller从外部源解组XML,请在XStreamMarshaller上设置supportedClasses属性,如以下示例所示:
默认情况下,XStream允许将任意类取消编组,这可能导致不安全的Java序列化效果。因此,我们不建议使用XStreamMarshaller从外部源(即Web)解组XML,因为这可能会导致安全漏洞。
如果选择使用XStreamMarshaller从外部源解组XML,请在XStreamMarshaller上设置supportedClasses属性,如以下示例所示:
<bean id =“ xstreamMarshaller” class =“ org.springframework.oxm.xstream.XStreamMarshaller”> <property name =“ supportedClasses” value =“ org.springframework.oxm.xstream.Flight” /> ... </ bean>
这样做可以确保只有注册的班级才有资格进行编组。 此外,您可以注册自定义转换器,以确保只能解组受支持的类。除了明确支持应支持的域类的转换器之外,您可能还想添加CatchAllConverter作为列表中的最后一个转换器。结果,不会调用具有较低优先级和可能的安全漏洞的默认XStream转换器。
这样做可以确保只有注册的班级才有资格进行编组。
此外,您可以注册自定义转换器,以确保只能解组受支持的类。除了明确支持应支持的域类的转换器之外,您可能还想添加CatchAllConverter作为列表中的最后一个转换器。结果,不会调用具有较低优先级和可能的安全漏洞的默认XStream转换器。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8