交换Web Service开发中对象数据类型的方法
作者:翁 彦
时间:2003-7-24
欢迎大家同我联系,enhydra_boy@tom.com
欢迎转载,转载请保留申明信息。
上次我谈了TOMCAT上如何快速开发Web service应用,并且举了个例子。但是传递的参数都是常见的数据类型,如果要传递复杂的数据类型,比如对象类型,那么应该如何来做呢。本篇,就是讨论这个问题。
我的方案是用一个string来实现,web service服务器端和客户端的复杂数据类型的交换。当然,这个string是一个xml格式字符串,它实现了复杂数据类型的存储。
那么,这个过程大致是这样的:
1 客户端发出SOAP的调用请求
2 服务端接受,从数据库中取出数据,并按要求加工成一个XML字符串
3 客户端接受xml字符串,并且解析出其中的信息。
反之,亦然。说道这里,应该说,这样的实现更本不难。那么,我们要解决的问题,是一套快速的开发方案,java开发中,使用对象来存储复杂的数据类型,vb中也有类的概念,那么当不同开发工具编写的程序进行数据交互通信的话,应该采用什么技术可以保证软件的开发速度和质量呢?这就是笔者本文的目的。
笔者认为,采用xml的专业设计工具来设计数据结构,利用第三方的开发工具,自动生成对应开发平台的源代码。这是较为快速和可靠的开发方法。
JAVA和VB都有相应的自动生成工具。JAVA是SUN Web Service Developer pack, VB有Microsoft SOAP ToolKit。简单说明如下:
1 利用XML SPY(XML设计工具)设计一个schema文件。
2 SUN Web Service Developer pack中jaxb可以根据schema自动生成java代码,编译成class文件。可以实现java程序把对象信息直接parse成xml字符串,和把xml字符串装载进来,初始化对象信息。
3 XML SPY把schema转换成xdr文件(xml data抽象文件),SOAP Toolkit中的Soap Message Object Generator自动生成VB类代码。功能同上。
下面,就让我们开始实践。
第一步,XML SCHEMA的设计
启动xml spy(如没有安装,下载并安装),新建一个schema文件,所有的设计都是可视化的。
保存,并得到一个EmployeeRoot.xsd文件。
第二步,自动生成java源程序。
先下载SUN Web Service Developer pack 1.1,安装并且按照文档配置环境。
在command窗口中,运行 %JAXB_HOME%/bin/xjc.bat EmployeeRoot.xsd -p com.sam.util.emp。命令成功后,会自动生成java源文件。
第三步,编译并且生成class代码。
在command窗口中,运行 %JAVA_HOME%/bin/javac com/sam/util/emp/*.java com/sam/util/emp/impl/*.java。
可以再运行jar命令打包。也可以运行javadoc为你的类生成技术文档。
第四部,建立一个Web Service,用于测试。
本例中,笔者使用的平台是TOMCAT+AXIS,大家可以看http://www.csdn.net/Develop/read_article.asp?id=19782 了解具体的配置。注意,请先把jaxb和jaxp的类库复制到$TOMCAT_HOME/axis/web-inf/libs下面。主要有:jaxb-api.jar, jaxb-libs.jar, jaxb-ri.jar, jaxb-xjc.jar, jaxp-api.jar。并把第三步得到的类库包也复制过来。
在axis目录下,创建一个EmpService.jws文件,代码如下:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.*;
import java.io.StringReader;
import java.io.StringWriter;
import com.sam.util.emp.*;
public class EmpService {
public String GetEmployees()
{
StringWriter sOut=new StringWriter();
try {
// create a JAXBContext capable of handling classes generated into JAXBContext jc= JAXBContext.newInstance("com.sam.util.emp" );
Unmarshaller u= jc.createUnmarshaller();
StringBuffer xmlStr=new StringBuffer ("<Employees><Employee><FirstName></FirstName> <MiddleName></MiddleName><LastName></LastName><SSN> </SSN></Employee><Version></Version></Employees>");
Employees emps=(Employees)u.unmarshal(
new StreamSource(new StringReader(
xmlStr.toString())));;
emps.getEmployee().clear();
Employee emp=new com.sam.util.emp.impl.EmployeeImpl();
emp.setFirstName("John");
emp.setMiddleName("");
emp.setLastName("Bob");
emp.setSSN("555-111");
emps.getEmployee().add(emp);
emp=new com.sam.util.emp.impl.EmployeeImpl();
emp.setFirstName("Tom");
emp.setMiddleName("");
emp.setLastName("Bill");
emp.setSSN("567-281");
emps.getEmployee().add(emp);
Marshaller m = jc.createMarshaller(); m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
StreamResult result = new StreamResult(sOut);
m.marshal(emps,result);
//System.out.println(sOut.toString());
} catch( JAXBException je ) {
je.printStackTrace();
return "";
}
return sOut.toString();
}
} |
第五步,利用xml spy中的convert dtd/schema,将employeeroot.xsd 转换成xml data文件(Employeeroot.xdr)。
转换出来的文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!-- edited with XML Spy v4.4 U (http://www.xmlspy.com) by weng yan (e-mao-e) --> <!--XML-Data generated by XML Spy v4.4 U (http://www.xmlspy.com)--> <Schema name="Untitled-schema" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes"> <ElementType name="Employee" model="closed" content="eltOnly" order="seq"> <group minOccurs="1" maxOccurs="1" order="seq"> <element type="FirstName" minOccurs="1" maxOccurs="1"/> <element type="MiddleName" minOccurs="1" maxOccurs="1"/> <element type="LastName" minOccurs="1" maxOccurs="1"/> <element type="SSN" minOccurs="1" maxOccurs="1"/> </group> </ElementType> <ElementType name="Employees" model="closed" content="eltOnly" order="seq"> <AttributeType name="xmlns" dt:type="string"/> <attribute type="xmlns"/> <group minOccurs="1" maxOccurs="1" order="seq"> <element type="Employee" minOccurs="1" maxOccurs="*"/> <element type="Version" minOccurs="1" maxOccurs="1"/> </group> </ElementType> <ElementType name="FirstName" model="closed" content="textOnly" dt:type="string"/> <ElementType name="LastName" model="closed" content="textOnly" dt:type="string"/> <ElementType name="MiddleName" model="closed" content="textOnly" dt:type="string"/> <ElementType name="SSN" model="closed" content="textOnly" dt:type="string"/> <ElementType name="Version" model="closed" content="textOnly" dt:type="string"/> </Schema> |
第六步,启动Visual Basic工程,如果安装过Soap ToolKit3的话,可以看到在Visual Basic中有一个add-in程序,叫Microsoft SOAP Messaging Object Generator,利用这个工具可以自动得到对应的vb类代码。利用这个工具,生成VB类代码,并且编译成一个ActiveX DLL。关于具体的内容,以后,我会在SOAP TOOLKIT工具使用介绍中专门解释。
第七步,编写客户端测试程序。在屏幕上放置一个文本框text1和list框list1。放置一个按钮cmdRead。
编写代码如下:
Private Sub cmdRead_Click()
On Error Resume Next
Dim SoapClient As Object
Dim sResult As String
Set SoapClient = CreateObject("MSSOAP.SoapClient30")
Call SoapClient.MSSoapInit2(Text1.Text, "", "", "EmpService", "")
If Err.Number <> 0 Then
MsgBox SoapClient.FaultString, vbExclamation
Exit Sub
End If
' Now the client can call an operation listed in the portType element |
本文地址:http://www.45fan.com/dnjc/71584.html