基于
XML
的数据共享
1.
引言
各应用系统与数据中心相连,通过数据中心来实现数据共享和路由。这种连接方式实现了数据的共享访问,保证了各业务系统的有效协同,同时又能保证各应用系统的相互独立性和低耦合性,从整体上提高了系统运作效率和安全性。
数据共享是为了能够把数据提供方指定的数据表table或视图view(于提供方数据库中)共享给获取方,及把数据中相关的提供方磁盘中的附属文件保存到获取方的磁盘中,并保证数据的合理响应、一致性、安全性和可操作性。
2.
数据共享
概要
2.1.
原理
数据共享原理如下图所示。

数据中心包括数据项管理、数据项XML Schema发布、WEB服务、中心数据库、日志管理等模块(其中WEB服务模块将部署在WEB服务器)。WEB服务处理来自数据代理端的接口调用。
数据代理包括数据提供和数据接收两部分。每个数据库运行一个数据代理端。数据提供和数据接收为周期性运行,并可分别设定周期。
数据提供:数据的打包(包括附件提供)、调用数据提供接口、共享消息发布、提供数据项管理。
数据接收:数据获取、附件获取、消息的监听及处理、数据转换、接收数据项管理等模块。
数据共享过程的时序图如下(现假设业务系统1为发送方(数据提供方)A,业务系统2为获取方(数据获取方)B,数据中心为C,A通过C共享数据给B):
1、由A定义要共享的关系型数据表(数据表Table或视图View,以下简称数据表)描述,提交给C及B。各代理端在自己系统中建立相应的导出项,根据A提供的描述形成自己的导入项。
2、C根据A提供的数据表描述,在系统中建立相应的共享数据目录、定义共享时的数据格式XML Schema(保存于WEB服务器)。B也可在本系统内建立数据接收项目及XML Element/字段对应关系,便于B接收数据。B方相应的数据库表结构自行定义,但要与数据接收项目的相关元素吻合。
3、A定时启动数据提供进程,把上一次没有共享(新增的或修改过)的记录根据规则打成XML包,此XML文件必须遵循上面定义的XML Schema。经过安全处理后通过C提供的接口保存至中心数据库,如果C确认接收则修改相应记录的标志位标识已经发送。如果数据要求的优先级较高,要求通知B(见3.2)。
4、B定时启动数据接收进程。通过C提供的查询接口知晓是否有向自己共享的数据,有则从中心数据库获取XML数据,收到数据后,经过XML-to-Table转换到数据库中,并修改C中的接收标志。A构建的XML包中包括附件信息,则B在解析时将提取相应的FTP地址或HTTP地址,加入到附件获取列表,从A的共享文件夹中下载到B的共享文件夹中。
2.2.
使用技术
Web服务(Web Service)实现互操作性,可用于沟通不同平台、编程语言和组件模型中的不同类型系统。Web Service需要以下技术的支持:XML、XML Schema、WSDL、UDDI、SOAP、RPC等。
在网络传输的SOAP数据的默认为明文(XML数据)。从安全性及一致性角度,必须对XML数据进行数字签名(XML-SIG)和数据加密(XML Encryption)。采用WSS(WS-Security)规范作为Web服务安全性解决方案,这里可以结合AXIS的Handler模型进行访问控制,具体实现方式见
附1。
数字证书作为XML数据共享双方身份证明的依据,是一个经证书授权中心(CA)数字签名的、包含证书申请者(公开密钥拥有者)个人信息及其公开密钥(由系统使用方定义)的文件。遵循X.509标准的证书是基于公开密钥体制(PKI)的数字证书,利用公共密钥加密系统来保护与验证公众的密钥。
Socket的采用主要用于提高共享数据的时效性,对于时效性要求比较高的数据,当数据成功的保存到数据中心后,及时通知获取方到中心共享数据。原来设计使用JMS技术,但是由于JMS技术在跨平台、语言无关性等方面不是太好,并不被现在常用的开发语言与平台支持,故采用Socket技术。
3.
规范说明
3.1.
XML SCHEMA
定义
W3C XML模式数据类型规范中定义了内置数据类型。其中包括了19种内置基本数据类型、25种内置派生数据类型。在此基础上,为适应平台的需求,自定义了两种数据类型:附件attachmentType、元数据类型名metaName。定义方式见附2。
系统中用到的内置基本数据类型:string、boolean、decimal、float、double、dateTime、date、base64Binary、anyURI;
系统中用到的内置派生数据类型:integer、long、int、short、byte。
数据库中的数据类型与http://www.w3.org/2001/XMLSchema中定义的数据类型的对应关系:
序号
|
ORACLE
数据类型
|
XML
对应数据类型
|
1
|
Blob
|
base64Binary
|
2
|
Date/ Timestamp
|
date
|
3
|
Number(p,s)/ DECIMAL(P,S) s>0
|
double
|
4
|
Number(p,s)/ DECIMAL(P,S) s=0
|
long
|
5
|
Varchar2/Char/nchar/nvachar2/XMLType/Clob 表示附件的除外
|
string
|
6
|
表示附件的。
|
attachmentType
|
7
|
BOOLEAN
|
boolean
|
注:
1、上表仅提供了Oracle中字段类型与xml类型的映射关系。如果要支持SQL Server或其它数据库系统中的数据类型,可以用近似类型替代或定制。
2、从数据库中的date型转换为XML字符串时,转换为“yyyy-MM-dd HH:mm:ss”型。
上表列出了数据库表中的类型转换为XML时的类型参考。逆向(把XML转换为数据表)时,考虑到数据类型的传递及数据的完整性,从XML到Oracle的数据类型对应表如下:
序号
|
XML
数据类型
|
ORACLE
可设置数据类型
|
1
|
base64Binary
|
Blob
|
2
|
date
|
Date/ Timestamp
|
3
|
double
|
Number(p,s)/ DECIMAL(P,S) s>0
|
4
|
long
|
Number(p,s)/ DECIMAL(P,S) s=0
|
5
|
string
|
Varchar2/Char/nchar/nvachar2/XMLType/Clob (Clob类型用于字节长大于4000的情况)
|
6
|
attachmentType
|
Varchar2/Char/nchar/nvachar2
|
7
|
boolean
|
BOOLEAN
|
注:上表中ORACLE可设置数据类型一栏中的类型并不完全,可根据系统需求和发送方的数据类型做参考定义。
把数据库中的要传输的大二进制对象(如Oracle中的BLOB类型、SQL Server中的Image类型),使用base64Binary编码,作为SOAP body中的一部分。
3.2.
数据描述
这里所说的数据表包括数据表Table(或视图View),由发送方提供或发送与接收两方协商定义。
描述文件要求提供如下资料:
1、提供方系统号及共享文件夹地址。
共享文件夹地址为FTP地址或HTTP地址,FTP包括用户名及密码。
2、数据表标识符及说明。
要求标识符不多于32个字符,并确保表名称唯一。
3、数据获取方及时效性要求。
4、相关字段属性描述。格式见下表:
No.
|
属性名称
|
说
明
|
类型
|
长度
|
主键
|
1
|
ID
|
主键
|
NUMBER
|
10
|
是
|
2
|
Pclass
|
拍摄分类
0-A类
1-B类
|
NUMBER
|
10
|
否
|
3
|
Rno
|
藏品号
|
VARCHR2
|
100
|
否
|
4
|
MONEY
|
金额
|
NUMBER
|
10.2
|
否
|
5
|
fileurl
|
图片。[附件] CRC32: File_checksum
|
VARCHR2
|
255
|
否
|
6
|
File_checksum
|
文件CRC32码
|
NUMBER
|
10
|
否
|
注:上表中属性名称表示字段名称,说明要详细。如例中第2个属性,要把所有定义的列举出来。为附件的应在说明栏中说明,并标明FTP或HTTP地址的相对地址(如:某字段在数据中保存为/subdir/1.txt对应的HTTP地址为http://IP:7001/sysA/updalodfile /subdir/1.txt,相对地址为http://IP:7001/sysA/updalodfile),还要求提供在本表中的CRC32码的字段名称。
Oracle常用的数据类型:CHAR、VARCHAR2、NCHAR、NVARCHAR2、DATE、LONG、RAW、LONG RAW、BLOB、CLOB、NCLOB、BFILE、ROWID、NROWID、NUMBER(P,S)、DECIMAL(P,S)、INTEGER、FLOAT、REAL、XMLType。
建议使用Oracle的如下数据类型:CHAR、VARCHAR2、NCHAR、NVARCHAR2、DATE、BLOB、CLOB、NUMBER(P,S)、DECIMAL(P,S)、XMLType。
通过数据表描述文件,数据中心形成该数据表的XML Schema文件(假设给定数据标识符为table123,则文件名为table123.xsd):
<?xml version="1.0" encoding="UTF-8"?>
<xs1:schema xmlns:xs2=" http://localhost:8080/schema"
xmlns:xs1 = " http://www.w3.org/2001/XMLSchema"
targetNamespace = " http://localhost:8080/schema"
elementFormDefault ="qualified" attributeFormDefault ="unqualified">
<xs1:element name="Records">
<xs1:complexType>
<xs1:sequence>
<xs1:element name="package_meta" type=¡±xs2:metaName">
<xs1:element ref="Record" maxOccurs="10"/><!--خ¶�͵-->
</xs1:sequence>
</xs1:complexType>
</xs1:element>
<xs1:schema xmlns:xs2=" http://localhost:8080/schema"
xmlns:xs1 = " http://www.w3.org/2001/XMLSchema"
targetNamespace = " http://localhost:8080/schema"
elementFormDefault ="qualified" attributeFormDefault ="unqualified">
<xs1:element name="Records">
<xs1:complexType>
<xs1:sequence>
<xs1:element name="package_meta" type=¡±xs2:metaName">
<xs1:element ref="Record" maxOccurs="10"/><!--خ¶�͵-->
</xs1:sequence>
</xs1:complexType>
</xs1:element>
<xs1:element name="orderItem">
<xs1:complexType>
<xs1:element name="ID" type="xs1:long"></xs1:element>
<xs1:element name=" Pclass ">
<xs1:simpleType>
<xs1:restriction base="xs1:long"><xs1:length value="10"/></xs1:restriction>
</xs1:simpleType>
</xs1:element>
<xs1:element name="Rno ">
<xs1:simpleType>
<xs1:restriction base="xs1:string"><xs1:length value="100"/></xs1:restriction>
</xs1:simpleType>
</xs1:element>
</xs1:schema>
生成的测试用的XML文件为:
<xs1:complexType>
<xs1:element name="ID" type="xs1:long"></xs1:element>
<xs1:element name=" Pclass ">
<xs1:simpleType>
<xs1:restriction base="xs1:long"><xs1:length value="10"/></xs1:restriction>
</xs1:simpleType>
</xs1:element>
<xs1:element name="Rno ">
<xs1:simpleType>
<xs1:restriction base="xs1:string"><xs1:length value="100"/></xs1:restriction>
</xs1:simpleType>
</xs1:element>
</xs1:schema>
生成的测试用的XML文件为:
<?xml version="1.0" encoding="gb2312" standalone="yes"?>
<!--?xml version="1.0" encoding="utf-8" standalone="no"?-->
<Records xmlns="gmip" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=" http://localhost:8080/schema
<!--?xml version="1.0" encoding="utf-8" standalone="no"?-->
<Records xmlns="gmip" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=" http://localhost:8080/schema
http://localhost:8080/schema/res.xsd">
<package_meta>dsfd</package_meta>
<Record>
<id>10</id>
<Pclass>10</Pclass>
<Rno>10</Rno>
</Record>
</Records>
<package_meta>dsfd</package_meta>
<Record>
<id>10</id>
<Pclass>10</Pclass>
<Rno>10</Rno>
</Record>
</Records>
3.3.
相关数据库设计
记录的删除处理:各包需要共享的数据库表记录不能物理删除,可用删除标志位做逻辑删除。删除标志字段:delflag varchar(2) 为1时表示删除,0表示为有效记录。删除记录时,置delflag为1,并置sendflag为0;
记录的发送处理:为了避免对一条记录在没有进行过修改的情况下多次发送,要求有共享标志字段。共享标志字段:sendflag varchar(2) 为1时表示已经共享至数据中心,0表示还没有共享至中心数据库。新增、修改记录置位0,共享至中心库成功后置位1。
数据表必须有一个整数类型(可以转换为Long)的主键值。每个附件字段要求有一个对应字段保存CRC32码,CRC32码在数据记录产生时由相应系统产生,并保存于数据库中。
3.4.
使用
SOCKET
发送通知
当发送的数据时效性要求比较高,要求通知获取方优先处理相应数据。
获取方启动Server Socket(服务器套接字)**端口,用于监听来自发送方的通知。发送方要减少发送信息的次数,确保每批次发送数据后通知获取方。
当获取方接收到消息后,优先启动数据共享进程从数据中心获取数据并转换到获取方的数据库中。
3.5.
数字签名与
SOAP
信息加密
安全性能要求:数据提供方与数据获取方之间的通信在网上传播时不应该被第三方看到或被篡改,即验证数据完整性与机密性。
提供方在发送数据之前要对要发送的SOAP包进行数字签名和加密。获取方在收到数据SOAP包后先对数据进行解密,然后验证。
数据的加密与数字签名,采用X.509证书,客户端和服务端都有相关的密匙库,其中:
client.keystore/bmc.keystore:客户端自身的身份信息;
client.truststore/bmc.truststore:客户端所信任的身份信息,在此例中也就是包含了服务器的身份信息;
server.keystore/bms.keystore:服务器自身的身份信息;
server.truststore/bms.truststore:服务器所信任的身份信息(即客户端身份信息)。
X.509证书文件的创建这里就不再详述。
使用证书库文件,获得私有key和相关证书,并对XML进行签名或对已经签名的文字进行解密,请参考JAVA安全编程相关书籍,这里就不详说了。
3.6.
数据共享接口规范
数据中心提供的接口为采用Web服务(Web Service),发布地址为:
http://
bjm_pack1/services/DataCenter.wsdl
其中
bjm_pack1表示数据中心的WEB地址(IP或域名)及端口。(以下同)
服务应该提供以下接口:
记录是否已提供:
检查指定的记录是否已经提供(共享至中心数据库中)。此接口不能作为是否要对某条记录构建XML提供依据。构建依据由提供方数据库表的发送标志位提供。
提供的XML数据:
指定数据记录,到中心数据库查找与此记录相关的XML内容。用于查询提供方自己共享出的XML数据。只能获得自己共享的数据。
共享数据ID集:
检查共享到的XML类型的记录集,并且支持多种状态。用于查询提供方自己的共享出的数据集合。
共享结果:
获得相关记录的共享结果。
共享至数据中心:
把提供方要共享的数据以XML形式保存到中心数据库,供获取方来提取。
数据接收:
获取方从数据中心获取一条没有被接收的记录。
修改共享状态:
如果接收者成功导入数据至数据库,要求修改数据中心的共享标志位。在调用此函数之前必须保证数据导入到数据库成功,否则指定数据将不能再次导入。
3.7.
附件定义
附件的表示见schema的attachmentType型说明。attachmentType由ftpurl、httpurl、dburl、sfvcode组成。
ftpurl表示附件在提供方的FTP服务器的地址,包括用户名及密码;
httpurl表示附件在提供方的WEB服务器的地址;
dburl表示附件保存在数据中的地址,为httpurl地址的后半部分,不包括BASE路径。
Sfvcode表示附件文件的SFV码。SFV码为10进制的值。用于检查附件是否被修改,如果没有被修改,则要做到不要重新下载附件。
文件SFV码是通过java.util.zip.CRC32获取的。SFV(simple file verification 简单文件校验),它采用的是crc32的校验算法。crc32校验产生32bit(8位十六进制数)校验值,所以一般大家看见的文件“sfv值”是一个8位的16进制数。由于crc32产生校验值时源数据块的每一个bit位都参与了计算,所以数据块中即使一位bit 发生变化,也会得到不同的crc32值。这里要求把8位的16进制转换为10进制。数据提供方获得CRC32校验值(获取方法见附4)后,保存在数据库中。
获取方确保只接收修改过或新增的附件文件。对于附件比较大的并同步性要求不是很高的,建议利用网络比较空闲的时间(如下班后)执行下载任务。
获取方判断文件是否要获取的依据:根据dburl,获取方可以知道文件的保存地址,如果文件不存在,则为新增文件,获取;如果文件存在,获取其CRC32值,如CRC32与现提供的CRC32不相等,则表示原文件已经修改,添加新记录要求重新下载文件。
3.8.
数据共享异常处理
共享系统运行过程中可能会出现的故障:
故
障
|
处
理
办
法
|
数据传输时网络故障
|
因为数据提供方或数据获取方调用数据中心接口时抛出异常(JAVA语言中为
java.rmi.RemoteException),由数据提供方或数据获取方捕捉异常,并对异常进行相应处理。检查配置是否正确,服务端是否启动,再检查网络是否通畅。
|
数据库连接故障
|
先检查网络,然后重新启动系统。数据中心、代理端分别处理。
|
非法访问
|
数据中心将不保存提供的数据或不读取请求的数据,由数据中心返回代表非法访问的代码-100(Long型)。
|
数据不合规范
|
数据提供方通过返回值来判断。如果得到异常返回值,数据提供方应该检查数据项配置是否正确。
|
调用返回错误码(见相应接口说明)
|
数据中心检查数据项配置和数据中心端的日志(包括数据库保存的状态码与系统log文件)。
数据提供方和数据获取方针对不同错误进行相应的处理。
|
转换XML为记录出错
|
数据获取方检查数据项配置。
|
获取附件出错
|
数据获取方检查数据提供方提供的访问方式是否正确。
|
作者:袁文聪