Spring正在成为JavaEE社区内一个非常受欢迎的框架
Spring的最新版本的特性之一是它的Object/XML(O/X)映射支持
这个API支持开发人员在Java对象和XML之间来回转换
在本文中
您将学习如何使用Spring中的Object/XML映射特性并了解它的优势
Spring作为Java应用程序框架已在Java开发社区中得到广泛使用SpringSource近日发布了最新版本Spring 版本文章主要针对Spring中的Object/XML映射分析使用Object/XML映射的特性与优势
Spring以其流行的科技词汇而着名比如dependencyinjection(依赖项注入)inversionofcontrol(控制反转)和aspectorientedprogramming(面向方面编程)等它还支持ModelViewController(MVC)模式很好地兼容用于数据访问的各种数据库驱动程序
另外它支持事务处理单元测试批处理和安全性鑒于Spring的良好声誉和悠久历史它通常是应用程序快速开发的首选框架但是最大的好处也许是Spring是免费的
Object/XML映射是什么?
Spring 的一个新特性是O/XMapperO/X映射器这个概念并不新鲜O代表ObjectX代表XML它的目的是在Java对象(几乎总是一个plainoldJavaobject或简写为POJO)和XML文档之间来回转换
例如您可能有一个带有几个属性的简单bean且您的业务需要将那个Java对象转换为一个XML文档Spring的O/XMapper能够为您解决那个问题如果反过来您需要将一个XML文档转换为一个简单JavabeanSpring的O/XMapper也能胜任有一点需要注意SpringO/XMapper只是定义由流行的第三方框架实现的统一的界面要利用Spring的O/X功能您需要一个在Java对象和XML之间来回转换的实用程序Castor就是这样一个流行的第三方工具本文将使用这个工具其他这样的工具包括XMLBeansJavaArchitectureforXMLBinding(JAXB)JiBX和XStream
编组和解组
进行O/X映射时您经常会看到编组(marshalling)和解组(unmarshalling)这两个术语编组指将Javabean转换成XML文档的过程这意味着Javabean的所有字段和字段值都将作为XML元素或属性填充到XML文件中有时编组也称为序列化(serializing)
如您所料解组是与编组完全相反的过程即将XML文档转换为Javabean这意味着XML文档的所有元素或属性都作为Java字段填充到Javabean中有时解组也称为反序列化(deserializing)
使用Spring的O/XMapper的好处
使用Spring的O/XMapper的一个最直接的好处是可以通过利用Spring框架的其他特性简化配置Spring的bean库支持将实例化的O/X编组器注入(即前面提到过的依赖项注入)使用那些编组器的对象重申一遍这将加快应用程序开发和部署
遵循坚实的面向对象的设计实践Spring Object/XML框架只定义两个接口Marshaller和Unmarshaller它们用于执行O/X功能这是使用这个框架的另一个重大好处这些接口的实现完全对独立开发人员开放开发人员可以轻松切换它们而无需修改代码例如如果您一开始使用Castor进行O/X转换但后来发现它缺乏您需要的某个功能这时您可以切换到XMLBeans而无需任何代码更改唯一需要做的就是更改Spring配置文件以使用新的Object/XML框架
使用Spring的Object/XML映射的另一个好处是统一的异常层次结构Spring框架遵循使用它的数据访问模块建立的模式方法是将原始异常对象包装到Spring自身专为O/XMapper建立的运行时异常中由于第三方提供商抛出的原始异常被包装到Spring运行时异常中您能够查明出现异常的根本原因您也不必费心修改代码以捕获异常因为异常已包装到一个运行时异常中以下几个运行时异常扩展了基础异常
XMLMappingException:GenericMarshallingFailureExceptionValidationFailureExceptionMarshallingFailureException和UnmarshallingFailureException
一个简单的演示
现在您已经了解了Spring的O/XMapper的背景和基础知识可以检验它的使用方法了在本文中您首先创建一个简单的Spring应用程序该程序独立于任何JavaEnterprise依赖项然后您创建一个简单的Java类它访问Spring的配置文件来实例化该类并注入O/X依赖项参见下载部分获取所有源代码文件(包括配置文件)的链接
编码
首先应该注意Spring配置文件清单是应用程序用于执行编组和解组操作的配置文件注意这个文件必须在运行时位于类路径中清单配置文件
<beansxmlnsbeansxmlns=
xmlns:xsi=instance
xsi:schemaLocation=
beansxsd>
<beanidbeanid=oxmExampleclass=comxyzOXMExample>
<propertynamepropertyname=marshallerref=castorMarshaller/>
<propertynamepropertyname=unmarshallerref=castorMarshaller/>
</bean>
<beanidbeanid=castorMarshallerclass=orgspringframeworkoxmcastorCastorMarshaller>
<propertynamepropertyname=mappingLocationvalue=classpath:mappingxml/>
</bean>
</beans>
如您所见这个配置文件只定义了两个bean这是为了简便起见第一个bean是用于执行演示的类comxyzOXMExample与该类关联的两个属性使用依赖项注入它们都使用castorMarshallerbean的一个实例注入这是在Spring框架中定义bean的标准方法经验丰富的Spring开发人员很快就会意识到这一点
另一个bean是castorMarshallerbean本身它是orgspringframeworkoxmcastorCastorMarshaller的一个实例orgspringframeworkoxmcastorCastorMarshaller主要用于包装Castor框架如前所述使用Spring的Object/XML功能需要使用一个第三方O/X框架在本例中这个第三方产品是Castor还要注意有一个属性使用castorMarshaller定义那是用于在Javabean和XML输出之间来回映射的映射文件这个文件称为mappingxml它必须在运行时位于类路径中我将稍后解释mappingxml文件的内容清单实际执行O/X映射器的代码的部分清单它是一个简单的Java类清单OXMExample类
publicclassOXMExample{
privatestaticfinalStringFILE_NAME=simplebeanxml;
privateSimpleBeansimpleBean;
privateMarshallermarshaller;
privateUnmarshallerunmarshaller;
publicvoidsetMarshaller(Marshallermarshaller){
thismarshaller=marshaller;
}
publicvoidsetUnmarshaller(Unmarshallerunmarshaller){
thisunmarshaller=unmarshaller;
}
publicvoidsaveSimpleBean()throwsIOException{
FileOutputStreamos=null;
try{
os=newFileOutputStream(FILE_NAME)
thismarshallermarshal(simpleBeannewStreamResult(os))
}finally{
if(os!=null){
osclose()
}
}
}
publicvoidloadSimpleBean()throwsIOException{
FileInputStreamis=null;
try{
is=newFileInputStream(FILE_NAME)
thissimpleBean
=(SimpleBean)thisunmarshallerunmarshal(newStreamSource(is))
}finally{
if(is!=null){
isclose()
}
}
}
publicstaticvoidmain(String[]args)throwsIOException{
ApplicationContextappContext
=newClassPathXmlApplicationContext(applicationContextxml)
OXMExampleex=(OXMExample)appContextgetBean(oxmExample)
exgo()
}
privatevoidgo()throwsIOException{
simpleBean=getSimpleBean()
saveSimpleBean()
loadSimpleBean()
Systemoutprintln(name:+simpleBeangetName())
Systemoutprintln(jobdescription:+simpleBeangetJobDescription())
Systemoutprintln(age:+simpleBeangetAge())
Systemoutprintln(executive:+simpleBeanisExecutive())
}
privateSimpleBeangetSimpleBean(){
SimpleBeansimpleBean=newSimpleBean()
simpleBeansetAge()
simpleBeansetExecutive(false)
simpleBeansetJobDescription(Janitor)
simpleBeansetName(MisterJones)
returnsimpleBean;
}
}
要解释清单必须首先介绍main方法因为该方法将先执行然后再接着介绍清单首先在main方法中您的代码捕获Spring应用程序的上下文就是您在清单中看到的配置文件这个文件必须在类路径中否则运行代码将产生一个异常
当您获得应用程序上下文时OXMExample的一个实例从该配置文件中提供的定义创建注意这个bean在代码中的名称(oxmExample)与配置文件中定义的名称(见清单)一致创建OXMExample的一个实例后调用go()方法这有点反常因为Spring框架实例化一个已经从命令行运行的对象但那只是为了实现演示目的而进行的简化go()方法在打印结果数据前完成个任务
创建SimpleBean的一个实例
编组该实例
解组从编组创建的XML文档
您使用getSimpleBean()方法实例化一个包含一个虚拟员工的信息的SimpleBean对象这个信息包含年龄(一个整数)工作描述(一个字符串)姓名(一个字符串)和该员工是否是执行官(一个布尔型)您使用测试数据和返回调用者的返回对象(在本例中为go()方法)填充字段您在编组发生时将这个bean写入一个XML文件在解组发生时读取那个XML文件的内容
saveSimpleBean()方法执行编组首先您获得一个指向simplebeanxml的对象然后您使用编组器对象(通过Spring的依赖项注入实例化)调用marshal方法这个方法需要两个参数
◆要被编组的对象(本例中为SimpleBean实例)
◆一个StreamResult对象它基本上表示一个XML输出抽象
loadSimpleBean()方法执行解组首先您获取一个指向simplebeanxml的FileInputStream对象然后您使用解组器对象(通过Spring的依赖项注入实例化)调用unmarshal方法唯一需要的参数是一个包装FileInputStream对象的StreamSource对象注意解组将创建一个泛型对象因此您必须将其显式设置为SimpleBean类型
即使这个类和Spring配置文件已经就绪您也还没有准备好运行这段代码还记得清单中的映射文件吗?您还需要定义那个映射文件定义代码如清单所示而且再说一遍它也必须在运行时位于类路径中清单mappingxml文件
<mapping>
<classnameclassname=comxyzSimpleBean>
<maptoxmlmaptoxml=simplebean/>
<fieldnamefieldname=agetype=integer>
<bindxmlnamebindxmlname=agenode=element/>
</field>
<fieldnamefieldname=executivetype=boolean>
<bindxmlnamebindxmlname=isexecutivenode=element/>
</field>
<fieldnamefieldname=jobDescriptiontype=string>
<bindxmlnamebindxmlname=jobnode=element/>
</field>
<fieldnamefieldname=nametype=string>
<bindxmlnamebindxmlname=namenode=element/>
</field>
</class>
</mapping>
清单中的映射文件特定于Object/XML映射的Castor实现第一个元素(class)定义要映射到一个XML输出的类您必须指定完整路径mapto元素提供XML文件的根元素的名称这很重要因为XML规范规定每个XML文件必须有一个根元素
每个field元素都将被映射到SimpleBean类中的一个特定字段每个field元素的bindxml子元素用于指定关于该字段的特定于XML的信息如对应的XML元素的名称每个字段的值应该是一个元素值还是一个属性值如您所见在本例中所有值都是元素值
测试
尽管代码已经编写完成但在执行这个应用程序之前您必须处理一些依赖项特定于Spring的依赖项有
orgspringframeworkasmMjar
orgspringframeworkbeansMjar
orgntextMjar
orgreMjar
orgspringframeworkexpressionMjar
orgspringframeworkoxmMjar
特定于Castor的依赖项有
castorcorejar
castorxmljar
您还需要commonsloggingjar和logjjar因为Spring框架需要它们所有这些JavaArchive(JAR)文件必须在运行时位于类路径中如果您在没有这些依赖项的情况下试图运行代码您很可能会收到一个异常指出某个类没有找到如果遇到这种情况只需双击您的类路径确保所有的必要依赖项已就绪事实上要成功编译这段代码您需要大部分JAR文件
您可以使用您钟爱的IDE或只是使用命令行来运行OXMExampleclass要从命令行运行只需从您的工作目录输入javacp[classpath]OXMExample这里的[classpath]是指向刚才提到的所有依赖项(JAR文件和配置文件)的类路径首次运行该程序后一个名为simplebeanxml的新文件将出现在您的工作目录中该文件的内容应该如清单所示清单simplebeanxml文件
<?xmlversionxmlversion=encoding=UTF?>
<simplebean>
<age></age>
<isexecutive>false</isexecutive>
<job>Janitor</job>
<name>MisterJones</name>
</simplebean>
清单显示了来自应用程序的编组端的输出而清单则显示来自应用程序的解组端的结果这些结果将在您的控制台中显示清单解组输出
name:MisterJones
jobdescription:Janitor
age:
executive:false
现在您已经成功地完成了您的首次SpringO/X映射测试现在最好做开发人员应该做的工作修改代码向类添加字段并将它们映射到XML文件删除一些字段并将它们从XML文件中移除参考Castor文档尝试一些更复杂的工作比如嵌套元素您可以随心所欲地尝试各种可能性
结束语
Spring的O/X映射接口是Spring框架的强大特性借助它您不仅可以将XML文档转换为Java对象还可以将Java对象转换为XML文档它利用Spring的一个关键优势依赖项注入通过结合使用依赖项注入和Spring的O/XMapper您可以轻松开发一个解决方案该方案可以使用任一O/X实现比如CastorXBeansJiBXJAXB和XStream由于各个特定实现是Spring强大的InversionofControl容器的一部分开发人员可以在多个特定O/X实现之间轻松切换而无需修改代码
Spring的O/XMapper还向开发人员提供一个统一的异常层次结构这意味着不管您使用哪个第三方实现抛出的运行时异常都是相同的再强调一次这将有利于在多个O/X供应商之间切换在Java开发社区中提供XML支持的Java应用程序非常热门并且Spring框架被广泛使用因此Spring的O/XMapper将受到全世界Java应用程序开发人员的欢迎