Web Service開發中對象數據類型的交換

作者:翁    <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

時間:2003-7-24

歡迎大家同我聯繫,[email protected]

歡迎轉載,轉載請保留申明信息。

 

上次我談了TOMCAT上如何快速開發Web service應用,並且舉了個例子。但是傳遞的參數都是常見的數據類型,如果要傳遞複雜的數據類型,比如對象類型,那麼應該如何來做呢。本篇,就是討論這個問題。

我的方案是用一個string來實現,web service服務器端和客戶端的複雜數據類型的交換。當然,這個string是一個xml格式字符串,它實現了複雜數據類型的存儲。

那麼,這個過程大致是這樣的:

1 客戶端發出SOAP的調用請求

2 服務端接受,從數據庫中取出數據,並按要求加工成一個XML字符串

3 客戶端接受xml字符串,並且解析出其中的信息。

反之,亦然。說道這裏,應該說,這樣的實現更本不難。那麼,我們要解決的問題,是一套快速的開發方案,java開發中,使用對象來存儲複雜的數據類型,vb中也有類的概念,那麼當不同開發工具編寫的程序進行數據交互通信的話,應該採用什麼技術可以保證軟件的開發速度和質量呢?這就是筆者本文的目的。

筆者認爲,採用xml的專業設計工具來設計數據結構,利用第三方的開發工具,自動生成對應開發平臺的源代碼。這是較爲快速和可靠的開發方法。

JAVAVB都有相應的自動生成工具。JAVASUN Web Service Developer pack, VBMicrosoft SOAP ToolKit。簡單說明如下:

1 利用XML SPY(XML設計工具)設計一個schema文件。

2 SUN Web Service Developer packjaxb可以根據schema自動生成java代碼,編譯成class文件。可以實現java程序把對象信息直接parsexml字符串,和把xml字符串裝載進來,初始化對象信息。

3 XML SPYschema轉換成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 瞭解具體的配置。注意,請先把jaxbjaxp的類庫複製到$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();

  }

}

運行http://localhost:8080/axis/EmpService.jws?wsdl, 可以看到該Service文件對應的wsdl接口。

 

第五步,利用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工具使用介紹中專門解釋。

 

第七步,編寫客戶端測試程序。在屏幕上放置一個文本框text1listlist1。放置一個按鈕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

    ' specified when calling mssoapinit().

    sResult = SoapClient.GetEmployees()

   

    If Err.Number <> 0 Then

        MsgBox SoapClient.FaultString, vbExclamation

        Exit Sub

    End If

   

   

    Dim oSoap As MSSMO.ISoapMessagePart

    Dim oDom As MSXML2.DOMDocument30

    Dim oEmps As EmployeesRoot.Employees

    Dim oEmp As EmployeesRoot.Employee

   

    'now we parse the xml data into our class

    Set oDom = New MSXML2.DOMDocument30

    If oDom.loadXML(sResult) Then

        Set oEmps = New EmployeesRoot.Employees

        Set oSoap = oEmps

        For Each oXMLNode In oDom.childNodes

            If oXMLNode.nodeType = NODE_ELEMENT Then

                If _

                    oXMLNode.baseName = oSoap.ElementName And _

                    oXMLNode.namespaceURI = oSoap.namespaceURI _

                Then

                    Set oSoap.Element = oXMLNode

                    Exit For

                End If

            End If

        Next

        List1.Clear

        For Each oEmp In oEmps.Employee

            List1.AddItem oEmp.SSN & vbTab & oEmp.FirstName & "," & oEmp.MiddleName & "," & oEmp.FirstName

        Next

End If

End Sub

運行,測試結果如下:

 

總結,通過這個例子,筆者認爲,它爲我們開發帶來了一種新的概念和思路。利用xml進行數據結構的設計,而代碼是基於設計的模式自動得到,採用這種開發方法使得,設計人員可以把精力集中在數據模型和業務邏輯上,而且,代碼的維護成本也大大降低。

發佈了29 篇原創文章 · 獲贊 0 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章