﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-esoa-文章分类-f. 架构.WebServices研究</title><link>http://www.blogjava.net/esoa/category/16074.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 23 Apr 2007 22:32:12 GMT</lastBuildDate><pubDate>Mon, 23 Apr 2007 22:32:12 GMT</pubDate><ttl>60</ttl><item><title>查看soap消息。</title><link>http://www.blogjava.net/esoa/articles/111973.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Thu, 19 Apr 2007 08:10:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/111973.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/111973.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/111973.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/111973.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/111973.html</trackback:ping><description><![CDATA[<p><a name=N10207><span class=atitle>设置 TCPMonitor 跟踪</span></a></p>
<p>我们还可以进行一项额外的操作，以检查通过网络传输的数据。WebSphere Application Server 提供了一个名为 TCPMonitor 工具，允许用户对 HTTP 消息进行跟踪。为了使用 TCPMonitor，我们将其放置在客户机和服务器之间。客户机当前直接与服务器进行交互。我们会将客户机定向到与 TCPMonitor 进行交互，而 TCPMonitor 会将通信数据转发给服务器。<br></p>
<p><strong>使用 TCP Monitor 監視 request 及 response SOAP conent：<br></strong>下載舊版 Axis library axis-bin-1_4.zip：<br><a href="http://apache.seekmeup.com/ws/axis/1_4/"><u><font color=#0000ff>http://apache.seekmeup.com/ws/axis/1_4/</font></u></a><br>解壓後把 axis.jar 複製至 D:\axis2\lib 裡,<br>進入 D:\axis2\lib 目錄<br>執行 D:\axis2\lib&gt; <span rgb(51, 255, 0); color: 102, 255);?>java -classpath axis.jar org.apache.axis.utils.tcpmon<br></span>就會彈出 TCPMonitor<br><strong>A)</strong> 为了利用 TCPMonitor，我们首先必须对客户机进行修改。编辑 HelloWorldClient.java，使其与以下所示内容类似：</p>
<br><br><a name=listing10><strong>清单 10. HelloWorldClient.java</strong></a><br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>
            package mypackage;
            import javax.xml.rpc.Stub;
            public class HelloWorldClient {
            public static void main(String[] args) throws Exception
            {
            HelloWorldServiceLocator hwlocator = new HelloWorldServiceLocator();
            HelloWorld hw = hwlocator.getHelloWorld();
            ((Stub) hw)._setProperty("javax.xml.rpc.service.endpoint.address",
            "http://localhost:1234/HelloWorldWAR/services/HelloWorld");
            System.out.println(hw.sayHello());
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p>添加了 <code>((Stub) hw)._setProperty("javax.xml.rpc.service.endpoint.address", "http://localhost:1234/HelloWorldWAR/services/HelloWorld");</code> 行，以将端点更改为客户机将用来发送通信数据的目标端点。在 HelloWorldServiceLocator.java 文件中通过以下代码行指定缺省端点地址：<code>private final java.lang.String helloWorld_address = "http://localhost:9080/HelloWorldWAR/services/HelloWorld";</code> <br>请注意，我们将端口从 9080 改为了 1234。此外，我们必须导入 java.xml.rpc.Stub 类，以将 HelloWorld 实例强制转换为 Stub 对象。</p>
<p><strong>B) </strong>运行 TCPMonitor 时，务必使用与 WebSphere Application Server 对应的 Java 版本。否则，可能会接收到一个 NullPointerException。发出以下命令：</p>
<br><br><a name=listing11><strong>清单 11. 运行 TCPMon</strong></a><br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>
            "%JAVA_HOME%" -Djava.ext.dirs="%WAS_EXT_DIRS%" com.ibm.ws.webservices.engine.utils.tcpmon
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p><strong>C)</strong> 指定下列值：</p>
<br><br><a name=listing12><strong>清单 12. TCPMon 中的值</strong></a><br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>
            Listen Port - 1234
            Target Hostname - localhost
            Target Port # - 9080
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>其窗口应与以下所示内容类似： <br><br><a name=fig2><strong>图 2. 设置 TCPMonitor 中的值</strong></a><br><img height=571 alt="设置 TCPMonitor 中的值" src="http://www.ibm.com/developerworks/cn/webservices/ws-noide2/tcpmon1.jpg" width=572> <br>
<p>接下来，单击 Add 按钮。这将配置 TCPMonitor 接收端口 1234 上的通信数据，并将其重定向到 9080。单击了 Add 按钮后，侦听器将自动运行。在 TCPMonitor 的顶部，将出现表示侦听器的选项卡。</p>
<p><strong>D)</strong> 通过以下命令重新编译并调用 Web 服务：</p>
<br><br><a name=listing13><strong>清单 13. 运行 HelloWorldClient</strong></a><br>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td class=code-outline>
            <pre class=displaycode>
            "%JAVA_HOME%\bin\javac"
            -extdirs "%WAS_CLASSPATH%;%WAS_EXT_DIRS%;." mypackage\*.java
            "%JAVA_HOME%\bin\java"
            -Djava.ext.dirs="%WAS_CLASSPATH%;%WAS_EXT_DIRS%;." mypackage.HelloWorldClient
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
<p><strong>E)</strong> 在 TCPMonitor 窗口中检查通信数据。SOAP 信封的内容将全部显示在一行中。Web 服务引擎为了节省空间，将避免发送换行字符。</p>
<br><br><a name=fig3><strong>图 3. TCPMonitor 输出</strong></a><br><img height=718 alt="TCPMonitor 输出" src="http://www.ibm.com/developerworks/cn/webservices/ws-noide2/tcpmon2.jpg" width=572> <br>
<p><strong>F)</strong> 为了使该 XML 更易于阅读，可以创建一个名为 tcptrace.xml 的新文件，并将该 XML 中的内容粘贴到其中。然后，可以使用 Mozilla Firefox 或 Microsoft Internet Explorer 打开该 XML 文件，以便查看应用了相应格式的内容。</p>
<img src ="http://www.blogjava.net/esoa/aggbug/111973.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2007-04-19 16:10 <a href="http://www.blogjava.net/esoa/articles/111973.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WSDL规则与示例(2)</title><link>http://www.blogjava.net/esoa/articles/86910.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Mon, 11 Dec 2006 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/86910.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/86910.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/86910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/86910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/86910.html</trackback:ping><description><![CDATA[
		<p>看看两段简单的JAVA代码,我们用它作为WSDL的服务实现代码:<br />//CatDTO.java<br />public class CatDTO<br />{<br />  private long id;<br />  private String name;<br />  public long getId()<br />  {<br />    return id;<br />  }<br />  public String getName()<br />  {<br />    return name;<br />  }<br />  public void setId(long id)<br />  {<br />    this.id = id;<br />  }<br />  public void setName(String name)<br />  {<br />    this.name = name;<br />  }<br />}<br />//Test.java<br />public class Test<br />{<br />  public String echo(CatDTO cd){<br />    return "Hello " + cd.getName();<br />  }<br />}<br />然后看看用它导出的WSDL:<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;wsdl:definitions targetNamespace="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" xmlns="<a href="http://schemas.xmlsoap.org/wsdl/">http://schemas.xmlsoap.org/wsdl/</a>" xmlns:apachesoap="<a href="http://xml.apache.org/xml-soap">http://xml.apache.org/xml-soap</a>" xmlns:impl="<a href="http://businessengine.hongsoft.com-impl/">http://businessEngine.hongsoft.com-impl</a>" xmlns:intf="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" xmlns:soapenc="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" xmlns:wsdl="<a href="http://schemas.xmlsoap.org/wsdl/">http://schemas.xmlsoap.org/wsdl/</a>" xmlns:wsdlsoap="<a href="http://schemas.xmlsoap.org/wsdl/soap/">http://schemas.xmlsoap.org/wsdl/soap/</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>"&gt;<br />//自定义类型<br /> &lt;wsdl:types&gt;<br />  &lt;schema targetNamespace="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" xmlns="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>"&gt;<br />   &lt;import namespace="<a href="http://schemas.xmlsoap.org/soap/encoding/" ?="">http://schemas.xmlsoap.org/soap/encoding/"/</a>&gt;<br />   //复合类型<br />   &lt;complexType name="CatDTO"&gt;<br />    &lt;sequence&gt;<br />     &lt;element name="id" type="xsd:long"/&gt;<br />     &lt;element name="name" nillable="true" type="xsd:string"/&gt;<br />    &lt;/sequence&gt;<br />   &lt;/complexType&gt;<br />   &lt;element name="CatDTO" nillable="true" type="intf:CatDTO"/&gt;<br />  &lt;/schema&gt;<br /> &lt;/wsdl:types&gt;</p>
		<p>   &lt;wsdl:message name="echoResponse"&gt;</p>
		<p>      &lt;wsdl:part name="echoReturn" type="xsd:string"/&gt;</p>
		<p>   &lt;/wsdl:message&gt;<br />   //表示复合类型的消息</p>
		<p>   &lt;wsdl:message name="echoRequest"&gt;</p>
		<p>      &lt;wsdl:part name="cd" type="intf:CatDTO"/&gt;</p>
		<p>   &lt;/wsdl:message&gt;<br />   //portType雷同一个类</p>
		<p>   &lt;wsdl:portType name="Test"&gt;</p>
		<p>      &lt;wsdl:operation name="echo" parameterOrder="cd"&gt;</p>
		<p>         &lt;wsdl:input message="intf:echoRequest" name="echoRequest"/&gt;</p>
		<p>         &lt;wsdl:output message="intf:echoResponse" name="echoResponse"/&gt;</p>
		<p>      &lt;/wsdl:operation&gt;</p>
		<p>   &lt;/wsdl:portType&gt;<br />   //与实现进行绑定,这里用SOAP方式</p>
		<p>   &lt;wsdl:binding name="TestSoapBinding" type="intf:Test"&gt;</p>
		<p>      &lt;wsdlsoap:binding style="rpc" transport="<a href="http://schemas.xmlsoap.org/soap/http" ?="">http://schemas.xmlsoap.org/soap/http"/</a>&gt;</p>
		<p>      &lt;wsdl:operation name="echo"&gt;</p>
		<p>         &lt;wsdlsoap:operation soapAction=""/&gt;</p>
		<p>         &lt;wsdl:input name="echoRequest"&gt;</p>
		<p>            &lt;wsdlsoap:body encodingStyle="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" namespace="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" use="encoded"/&gt;</p>
		<p>         &lt;/wsdl:input&gt;</p>
		<p>         &lt;wsdl:output name="echoResponse"&gt;</p>
		<p>            &lt;wsdlsoap:body encodingStyle="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" namespace="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" use="encoded"/&gt;</p>
		<p>         &lt;/wsdl:output&gt;</p>
		<p>      &lt;/wsdl:operation&gt;</p>
		<p>   &lt;/wsdl:binding&gt;<br />  //用于发布服务</p>
		<p>   &lt;wsdl:service name="TestService"&gt;</p>
		<p>      &lt;wsdl:port binding="intf:TestSoapBinding" name="Test"&gt;</p>
		<p>         &lt;wsdlsoap:address location="<a href="http://localhost:8080/hongsoft/services/Test" ?="">http://localhost:8080/hongsoft/services/Test"/</a>&gt;</p>
		<p>      &lt;/wsdl:port&gt;</p>
		<p>   &lt;/wsdl:service&gt;</p>
		<p>&lt;/wsdl:definitions&gt;</p>
<img src ="http://www.blogjava.net/esoa/aggbug/86910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-12-11 15:01 <a href="http://www.blogjava.net/esoa/articles/86910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WSDL文件详解(3)</title><link>http://www.blogjava.net/esoa/articles/86909.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Mon, 11 Dec 2006 07:00:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/86909.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/86909.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/86909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/86909.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/86909.html</trackback:ping><description><![CDATA[
		<font face="宋体">用的介面，會利用 Java 的多載功能。但這對使用 COM 的客戶端倒無所謂，因為 COM 並不支援多載。<br /><br />&lt;binding&gt; 與 &lt;operation&gt; 元素<br />Binding 區段是，指定通訊協定、序列化、與編碼的地方。若 Types、Messages、與 PortType 等區段負責抽象的資料內容，那麼 Binding 區段便負責處理資料傳輸的具體細節。Binding 區段負責使前三個區段的抽象具體化。<br /><br />將繫結規格從資料與訊息宣告中分離出來的意義是，執行相同業務的服務提供者，可將一組作業 (portType) 標準化。若欲凸顯自身的差異，每個提供者可另外提供自訂繫結。讓 WSDL 擁有匯入 construct 是有好處的；因為如此一來，即可遠離 Bindings 與 Services 區段，將抽象定義置於自身的檔案中；並可將其散佈於服務提供者間，讓他們把抽象定義設定成標準。例如，銀行可標準化，一組抽象 WSDL 文件詳盡說明的銀行作業。但每家銀行還是可以自由地，「自訂」基礎通訊協定、序列最佳化、與編碼。<br /><br />下列為 Binding 區段的 WSDL 多載範例，於此重複以方便詳細討論：<br /><br />&lt;binding name="fooSampleBinding" type="wsdlns:fooSamplePortType"&gt;<br />&lt;stk:binding preferredEncoding="UTF-8" /&gt;<br />&lt;soap:binding style="rpc" <br />transport="http://schemas.xmlsoap.org/soap/http"/&gt;<br />&lt;operation name="foo"&gt;<br />&lt;soap:operation soapAction="http://tempuri.org/action/foo1"/&gt;<br />&lt;input name="foo1"&gt;<br />&lt;soap:body use="encoded" <br />namespace="http://tempuri.org/message/" <br />encodingStyle=<br />"http://schemas.xmlsoap.org/soap/encoding/" /&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br />&lt;operation name="foo"&gt;<br />&lt;soap:operation soapAction="http://tempuri.org/action/foo2"/&gt;<br />&lt;input name="foo2"&gt;<br />&lt;soap:body use="encoded" <br />namespace="http://tempuri.org/message/" <br />encodingStyle=<br />"http://schemas.xmlsoap.org/soap/encoding/" /&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br />&lt;/binding&gt;<br /><br />&lt;binding&gt; 元素會有個名稱 (本例中為「fooSampleBinding」)，以方便 Services 區段的 &lt;port&gt; 元素參照。它有個參照 &lt;portType&gt; 的「type」屬性，在本例中為「wsdlns:fooSamplePortType」。第二行是 MSTK2 擴充元素 &lt;stk:binding&gt;，它可指定 preferredEncoding，或稱「UTF-8」。<br /><br />&lt;soap:binding&gt; 元素可指定，使用的樣式 (rpc) 與傳輸。傳輸屬性會參照命名空間，以確定所使用的 HTTP SOAP 通訊協定。<br /><br />有兩個 &lt;operation&gt; 元素具有相同的名稱「foo」。這兩個作業不同之處在於，兩個不同的 &lt;input&gt; 名稱：「foo1」與「foo2」。在兩個 &lt;operation&gt; 元素中，&lt;soap:operation&gt; 元素的「soapAction」屬性皆相同，都是一個 URI。soapAction 屬性是 SOAP 專屬的 URI，並逐字依 SOAP 訊息使用。以此方式取得的 SOAP 訊息，會有個 SOAPAction 標頭；而且還會以 &lt;soap:operation&gt; 元素中的 URI 為其值。雖然 HTTP 繫結需要 soapAction 屬性，但非 HTTP 繫結則不用。本文刊出時，其用途仍然不明。就本範例而言，它似乎可用來區別兩個不同的「foo」作業。SOAP 1.1 宣稱，soapAction 可用來識別訊息的「目的 (intent)」。它更建議伺服端，可用此屬性路由訊息，而不用剖析整個訊息。實務上，其用途差異很大。&lt;soap:operation&gt; 元素也可以含另一個名為「style」的屬性；若特定作業需要覆寫 &lt;soap:binding&gt; 元素中所指定的樣式，則可使用此屬性。<br /><br />&lt;operation&gt; 元素所含的 &lt;input&gt;、&lt;output&gt;、與 &lt;fault&gt; 元素，可對應 PortTypes 區段的相同元素。在上例中出現的只有 &lt;input&gt; 元素。在本例中，這三個元素都各有一個選擇性的「name」屬性，可用以區別名稱相同的作業。在範例的 &lt;input&gt; 元素中，有個 &lt;soap:body&gt; 元素，它可指定輸入結果 SOAP 訊息之 &lt;body&gt; 的內容。此元素有下列屬性：<br /><br />Use<br />它是用以指定資料採「編碼 (encoded)」或「常值 (literal)」。「常值」的意義是，結果 SOAP 訊息所含資料的格式，完全依照抽象定義 (Types、Messages、與 PortTypes 區段) 的指定規格 。「編碼」的意義是，「encodingStyle」屬性 (參考下文) 會指定編碼方式。 <br />Namespace<br />每個 SOAP 訊息的主體，都有自己的命名空間，以防止名稱衝突。此屬性所指定的 URI，會逐字使用於結果 SOAP 訊息之中。 <br />EncodingStyle<br />以 SOAP 的編碼方式而言，URI 的值應該是「http://schemas.xmlsoap.org/soap/encoding」。 <br />文件樣式繫結<br />在上一區段中，&lt;soap:binding&gt; 元素有個類型屬性被設定成「rpc」。若將此屬性設定成「document」，即可改變訊息在線上的排序。此時這些訊息便成了文件傳輸，而不再是函數簽章。在此繫結類型中，&lt;message&gt; 元素是定義文件格式，而非函數簽章。請參考下例中的 WSDL 片段：<br /><br />&lt;definitions<br />xmlns:stns="(SchemaTNS)"<br />xmlns:wtns="(WsdlTNS)"<br />targetNamespace="(WsdlTNS)"&gt;<br /><br />&lt;schema targetNamespace="(SchemaTNS)"<br />elementFormDefault="qualified"&gt;<br />&lt;element name="SimpleElement" type="xsd:int"/&gt;<br />&lt;element name="CompositElement" type="stns:CompositeType"/&gt;<br />&lt;complexType name="CompositeType"&gt;<br />&lt;all&gt;<br />&lt;element name='a' type="xsd:int"/&gt;<br />&lt;element name='b' type="xsd:string"/&gt;<br />&lt;/all&gt;<br />&lt;/complexType&gt;<br />&lt;/schema&gt;<br /><br />&lt;message...&gt;<br />&lt;part name='p1' type="stns:CompositeType"/&gt;<br />&lt;part name='p2' type="xsd:int"/&gt;<br />&lt;part name='p3' element="stns:SimpleElement"/&gt;<br />&lt;part name='p4' element="stns:CompositeElement"/&gt;<br />&lt;/message&gt;<br />?&lt;/definitions&gt;<br /><br />此結構描述有 SimpleElement 與 CompositeElement 兩個元素，以及一個宣告類型 (CompositeType)。所宣告的唯一 &lt;message&gt; 元素有四個部分 (part)：p1 是 CompositeType 類型；p2 是 int 類型；p3 是 SimpleElement；而 p4 是 CompositeElement。下表是四種繫結的比較，依照「使用/類型」分別為：rpc/literal、document/literal、rpc/encoded、與 document/encoded。本表可說明，每種繫結方式反映在線上的實際情況。<br /><br />rpc / literal<br />&lt;operation name="method1" style="rpc" ...&gt;<br />&lt;input&gt;<br />&lt;soap:body parts="p1 p2 p3 p4" <br />use="literal"<br />namespace="(MessageNS)"/&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br /><br />線上情形：<br />&lt;soapenv:body... xmlns:mns="(MessageNS)"<br />xmlns:stns="(SchemaTNS)"&gt;<br />&lt;mns:method1&gt;<br />&lt;mns:p1&gt;<br />&lt;stns:a&gt;123&lt;/stns:a&gt;<br />&lt;stns:b&gt;hello&lt;/stns:b&gt;<br />&lt;/mns:p1&gt;<br />&lt;mns:p2&gt;123&lt;/mns:p2&gt;<br />&lt;mns:p3&gt;<br /><br />&lt;stns:SimpleElement&gt;<br /><br />123<br /><br />&lt;/stns:SimpleElement&gt;<br />&lt;/mns:p3&gt;<br />&lt;mns:p4&gt;<br />&lt;stns:CompositeElement&gt;<br />&lt;stns:a&gt;123&lt;/stns:a&gt;<br />&lt;stns:b&gt;hello&lt;/stns:b&gt;<br />&lt;/stns:CompositeElement&gt;<br />&lt;/mns:p4&gt;<br />&lt;/mns:method1&gt;<br />&lt;/soapenv:body&gt;<br />document / literal / type=<br />&lt;operation name="method1" <br />style="document" ...&gt;<br />&lt;input&gt;<br />&lt;soap:body parts="p1" use="literal"&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br /><br />線上情形：<br /><br />&lt;soapenv:body... xmlns:stns="(SchemaTNS)"&gt;<br />&lt;stns:a&gt;123&lt;/stns:a&gt;<br />&lt;stns:b&gt;hello&lt;/stns:b&gt;<br />&lt;/soapenv:body&gt;<br /><br />rpc / encoded <br />&lt;operation name="method1" style="rpc" ...&gt;<br />&lt;input&gt;<br />&lt;soap:body parts="p1 p2" use="encoded" <br />encoding= <br />"http://schemas.xmlsoap.org/soap/encoding/"<br />namespace="(MessageNS)"/&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br /><br />線上情形：<br />&lt;soapenv:body... xmlns:mns="(MessageNS)"&gt;<br />&lt;mns:method1&gt;<br />&lt;p1 TARGET="_self" HREF="#1"/&gt;<br />&lt;p2&gt;123&lt;/p2&gt;<br />&lt;/mns:method1&gt;<br />&lt;mns:CompositeType id="#1"&gt;<br />&lt;a&gt;123&lt;/a&gt;<br />&lt;b&gt;hello&lt;/b&gt;<br />&lt;/mns:CompositeType&gt;<br />&lt;/soapenv:body&gt;<br />document / literal / element=<br />&lt;operation name="method1" <br />style="document" ...&gt;<br />&lt;input&gt;<br />&lt;soap:body parts="p3 p4" <br /><br />use="literal"&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br /><br />線上情形：<br /><br />&lt;soapenv:body... xmlns:stns="(SchemaTNS)"&gt;<br />&lt;stns:SimpleElement&gt;<br /><br />123<br /><br />&lt;/stns:SimpleElement&gt;<br />&lt;stns:CompositeElement&gt;<br />&lt;stns:a&gt;123&lt;/stns:a&gt;<br />&lt;stns:b&gt;hello&lt;/stns:b&gt;<br />&lt;/stns:CompositeElement&gt;<br />&lt;/soapenv:body&gt;<br /><br />document / encoded<br />&lt;operation name="method1" <br />style="document" ...&gt;<br />&lt;input&gt;<br />&lt;soap:body parts="p1 p2" use="encoded" <br />encoding=<br /><br />"http://schemas.xmlsoap.org/soap/encoding/"<br />namespace="(MessageNS)"/&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br /><br />線上情形：<br />&lt;soapenv:body... xmlns:mns="(MessageNS)"&gt;<br />&lt;mns:CompositeType&gt;<br />&lt;a&gt;123&lt;/a&gt;<br />&lt;b&gt;hello&lt;/b&gt;<br />&lt;/mns:CompositeType&gt;<br />&lt;soapenc:int&gt;123&lt;/soapenc:int&gt;<br />&lt;/soapenv:body&gt;<br /><br /><br />&lt;service&gt; 與 &lt;port&gt; 元素<br />服務即是一組 &lt;port&gt; 元素。每個 &lt;port&gt; 元素，都以一對一的方式，關連一個位置與 &lt;binding&gt;。若有一個以上的 &lt;port&gt; 元素，與相同的 &lt;binding&gt; 關連，便可以使用其它 URL 作為替換。<br /><br />在 WSDL 文件中，可以有一個以上的 &lt;service&gt; 元素。多個 &lt;service&gt; 元素，可以有許多用途。其中之一便是，根據 URL 的目的地，將傳輸埠群組化。因此，我只要使用另一個 &lt;service&gt;，就可以重新導向所有股票報價要求；而且我的客戶端程式依然可以正常咦鳎@是因為在這類的服務群組化中，通訊協定完全不會更動其它的服務。多個 &lt;service&gt; 服務的另一個用途是為了，根據基礎通訊協定，對傳輸埠進行分類。例如，可將所有的 HTTP 傳輸埠，置於一個 &lt;service&gt;；所有的 SMTP 傳輸埠置於另一個 &lt;service&gt;。客戶端便可根據它能處理的通訊協定，搜尋相對的 &lt;service&gt;。<br /><br />&lt;service name="FOOService"&gt;<br />&lt;port name="fooSamplePort" binding="fooSampleBinding"&gt;<br />&lt;soap:address <br />location="http://carlos:8080/fooService/foo.asp"/&gt;<br />&lt;/port&gt;<br />&lt;/service&gt;<br /><br />在一份 WSDL 文件中，&lt;service&gt; 的「name」屬性，可區分出個別服務的不同。因為一個服務可能會有幾個傳輸埠，所以傳輸埠也必須有「name」屬性。<br /><br />總結<br />本文已經說明了 WSDL 文件最顯著的 SOAP 特色。但應該聲明的是，WSDL 絕不僅只能在 HTTP 上說明 SOAP 而已。在說明 SOAP 上，WSDL 的表達能力絕對足以使用 HTTP-POST、HTTP-GET、SMTP、與其它通訊協定。只要使用 WSDL，不論是程式開發人員或一般使用者，都可輕鬆處理 SOAP。個人深信，WSDL 與 SOAP 的結合，將可引進全新的應用程式類別，以更徹底地利用各種網路服務。<br /><br />在 WSDL 的命名空間，有各種 XML 元素。下表整理了這些元素、屬性、與內容，以供參考：<br /><br />元素 屬性 內容 (子項) <br />&lt;definitions&gt; name<br />targetNamespace<br />xmlns (其它命名空間) &lt;types&gt;<br />&lt;message&gt;<br />&lt;portType&gt;<br />&lt;binding&gt;<br />&lt;service&gt; <br />&lt;types&gt; (無) &lt;xsd:schema&gt; <br />&lt;message&gt; name &lt;part&gt; <br />&lt;portType&gt; name &lt;operation&gt; <br />&lt;binding&gt; name<br />type &lt;operation&gt; <br />&lt;service&gt; name &lt;port&gt; <br />&lt;part&gt; name<br />type (空值) <br />&lt;operation&gt; name<br />parameterOrder &lt;input&gt;<br />&lt;output&gt;<br />&lt;fault&gt; <br />&lt;input&gt; name<br />message (空值) <br />&lt;output&gt; name<br />message (空值) <br />&lt;fault&gt; name<br /><br />message (空值) <br />&lt;port&gt; name<br />binding &lt;soap:address&gt; <br /><br />資源：<br />WSDL 1.1 <br />SOAP 1.1 <br />XML 結構描述入門 <br />MS SOAP Toolkit 下載網站 <br />IDL 至 WSDL 的轉譯工具 <br />含 WSDL 至 VB 之 Proxy 產生器的免費網路資源 <br />PocketSOAP：SOAP 之相關元件、工具、與原始程式碼 </font>
		<br />
<img src ="http://www.blogjava.net/esoa/aggbug/86909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-12-11 15:00 <a href="http://www.blogjava.net/esoa/articles/86909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WSDL文件详解(2)</title><link>http://www.blogjava.net/esoa/articles/86908.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Mon, 11 Dec 2006 06:59:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/86908.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/86908.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/86908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/86908.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/86908.html</trackback:ping><description><![CDATA[
		<p>
				<font face="宋体">WSDL 類型與訊息區段中的 XML 結構描述<br />WSDL 的資料類型，是根據目前 W3C Recommendation 的「XML Schema: Datatypes」(XSD)。此文件共有三種不同的版本 (1999、2000/10、與 2001)，若欲指定特定 WSDL 檔案所使用的版本，請在 &lt;definitions&gt; 元素中，將其宣告為命名空間的屬性。方法如下：<br /><br />xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br /><br />本文僅以 2001 版為考量。WSDL 標準的擁護者，也大力建議使用 2001 版。<br /><br />在本節與後續章節中，採用的字首或命名空間速記法如下：<br /><br />字首 對應的命名空間 說明 <br />soapenc http://schemas.xmlsoap.org/soap/encoding SOAP 1.1 編碼 <br />wsdl http://schemas.xmlsoap.org/wsdl/soap WSDL 1.1 <br />xsd http://www.w3.org/2001/XMLSchema XML Schema <br /><br />XSD 基本類型<br />下表直接取自 MSTK2 文件，列舉了 MSTK2 支援的所有 XSD 基本類型。該表說明，位於客戶端與伺服端的 WSDL 讀者，如何在 VB、C++、與 IDL 中，將 XSD 類型對應至不同與對等的類型。<br /><br />XSD (Soap) 類型 不同的類型 VB C++ IDL 註解 <br />anyURI VT_BSTR String BSTR BSTR <br />base64Binary VT_ARRAY | VT_UI1 Byte() SAFEARRAY SAFEARRAY(unsigned char) <br />boolean VT_BOOL Boolean VARIANT_BOOL VARIANT_BOOL <br />byte VT_I2 Integer short short 轉換時驗證範圍。 <br />date VT_DATE Date DATE DATE 時間設為 oo:oo:oo <br />dateTime VT_DATE Date DATE DATE <br />double VT_R8 Double double double <br />duration VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />ENTITIES VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />ENTITY VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />float VT_R4 Single float float <br />gDay VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />gMonth VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />gMonthDay VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />gYear VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />gYearMonth VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />ID VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />IDREF VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />IDREFS VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />int VT_I4 long long long <br />integer VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />language VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />long VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />Name VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />NCName VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />negativeInteger VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />NMTOKEN VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />NMTOKENS VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />nonNegativeInteger VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />nonPositiveInteger VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />normalizedString VT_BSTR String BSTR BSTR <br />NOTATION VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />number VT_DECIMAL Variant DECIMAL DECIMAL <br />positiveInteger VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />QName VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />short VT_I2 Integer short short <br />string VT_BSTR String BSTR BSTR <br />time VT_DATE Date DATE DATE Day 設定成 1899 年 12 月 30 日 <br />token VT_BSTR String BSTR BSTR 不執行驗證或轉換 <br />unsignedByte VT_UI1 Byte unsigned char unsigned char <br />unsignedInt VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />unsignedLong VT_DECIMAL Variant DECIMAL DECIMAL 轉換時驗證範圍。 <br />unsignedShort VT_UI4 long long long 轉換時驗證範圍。 <br /><br />XSD 定義兩組內建的資料類型：基本類型與衍生類型。若需進一步資訊，可前往 http://www.w3.org/TR/2001/PR-xmlschema-2-20010330，檢視內建類型的階層架構。<br /><br />複雜類型<br />XML Schema 可定義複雜類型，也就是 C 中的 struct。例如，下列 C struct 的相對定義方式為：<br /><br />typedef struct {<br />string firstName;<br />string lastName;<br />long ageInYears;<br />float weightInLbs;<br />float heightInInches;<br />} PERSON;<br /><br />若使用 XML Schema 可以撰寫成：<br /><br />&lt;xsd:complexType name="PERSON"&gt;<br />&lt;xsd:sequence&gt;<br />&lt;xsd:element name="firstName" type="xsd:string"/&gt;<br />&lt;xsd:element name="lastName" type="xsd:string"/&gt;<br />&lt;xsd:element name="ageInYears" type="xsd:int"/&gt;<br />&lt;xsd:element name="weightInLbs" type="xsd:float"/&gt;<br />&lt;xsd:element name="heightInInches" type="xsd:float"/&gt;<br />&lt;/xsd:sequence&gt;<br />&lt;/xsd:complexType&gt;<br /><br />不過，&lt;complexType&gt; 所能表示的，絕不僅止於 struct 的對應而已。除了 &lt;sequence&gt; 之外，它還可以有其它的子元素。若不用 &lt;sequence&gt;，也可以使用 &lt;all&gt;：<br /><br />&lt;xsd:complexType name="PERSON"&gt;<br />&lt;xsd:all&gt;<br />&lt;xsd:element name="firstName" type="xsd:string"/&gt;<br />&lt;xsd:element name="lastName" type="xsd:string"/&gt;<br />&lt;xsd:element name="ageInYears" type="xsd:int"/&gt;<br />&lt;xsd:element name="weightInLbs" type="xsd:float"/&gt;<br />&lt;xsd:element name="heightInInches" type="xsd:float"/&gt;<br />&lt;/xsd:all&gt;<br />&lt;/xsd:complexType&gt;<br /><br />其意義則是，成員變數 &lt;element&gt; 可以任何順序輸入，且每一項都具有選擇性。這點便與 C struct 的使用方式不同了。<br /><br />請注意範例中，string (字串)、int (整數)、float (浮點數) 等內建資料類型的使用方式。C 的字串在 XML 中也是字串，且浮點數還是浮點數。但 C 的 long (長整數)，在 XML 則是 int (請參考上表)。<br /><br />在 WSDL 檔案中，Types 區段是宣告上述複雜類型的位置。例如，PERSON 類型可以下列方式宣告，並將其用於 Messages 區段中：<br /><br />&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;definitions ?&gt;<br />&lt;types&gt;<br />&lt;schema targetNamespace="someNamespace" <br />xmlns:typens="someNamespace" &gt;<br />&lt;xsd:complexType name="PERSON"&gt;<br />&lt;xsd:sequence&gt;<br />&lt;xsd:element name="firstName" type="xsd:string"/&gt;<br />&lt;xsd:element name="lastName" type="xsd:string"/&gt;<br />&lt;xsd:element name="ageInYears" type="xsd:int"/&gt;<br />&lt;xsd:element name="weightInLbs" type="xsd:float"/&gt;<br />&lt;xsd:element name="heightInInches" type="xsd:float"/&gt;<br />&lt;/xsd:sequence&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;/schema&gt;<br />&lt;/types&gt;<br /><br />&lt;message name="addPerson"&gt;<br />&lt;part name="person" type="typens:PERSON"/&gt;<br />&lt;/message&gt;<br /><br />&lt;message name="addPersonResponse"&gt;<br />&lt;part name="result" type="xsd:int"/&gt;<br />&lt;/message&gt;<br /><br />&lt;/definitions&gt;<br /><br />在上述的範例中，第一個訊息的名稱是「addPerson」，它有個類型為「PERSON」的 &lt;part&gt;。在 Types 區段中，類型 PERSON 會被宣告為複雜類型。<br /><br />起始 MSTK2 SoapClient 時，若在上述片段使用完整的 WSDL 檔案，它便可成功地剖析該檔案。不過，它還是不能將函數呼叫，傳送至 &lt;addPerson&gt;。這是因為 SoapClient 本身不知道如何處理複雜類型；它需要自訂的類型對應器 (mapper) 才能處理複雜類型。在 MSTK2 文件中有一個範例應用程式，它含有自訂的類型對應器。<br /><br />另外還有一個方法，可將 &lt;part&gt; 元素，關連至類型宣告。這個方法使用的是元素，而非類型屬性。下個範例會在 Types 區段中，先宣告兩個元素 (「Person」與「Gender」)；然後在「addPerson」的 &lt;message&gt; 中，再使用元素屬性參照它們。<br /><br />&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;definitions ?&gt;<br />&lt;types&gt;<br />&lt;schema targetNamespace="someNamespace" <br />xmlns:typens="someNamespace" &gt;<br />&lt;element name="Person"&gt;<br />&lt;xsd:complexType&gt;<br />&lt;xsd:sequence&gt;<br />&lt;xsd:element name="firstName" type="xsd:string"/&gt;<br />&lt;xsd:element name="lastName" type="xsd:string"/&gt;<br />&lt;xsd:element name="ageInYears" type="xsd:int"/&gt;<br />&lt;xsd:element name="weightInLbs" type="xsd:float"/&gt;<br />&lt;xsd:element name="heightInInches" type="xsd:float"/&gt;<br />&lt;/xsd:sequence&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;/element&gt;<br />&lt;element name="Gender"&gt;<br />&lt;xsd:simpleType&gt;<br />&lt;xsd:restriction base="xsd:string"&gt;<br />&lt;xsd:enumeration value="Male" /&gt;<br />&lt;xsd:enumeration value="Female" /&gt;<br />&lt;/xsd:restriction&gt;<br />&lt;/xsd:simpleType&gt;<br />&lt;/element&gt;<br />&lt;/schema&gt;<br />&lt;/types&gt;<br /><br />&lt;message name="addPerson"&gt;<br />&lt;part name="who" element="typens:Person"/&gt;<br />&lt;part name="sex" element="typens:Gender"/&gt;<br />&lt;/message&gt;<br /><br />&lt;message name="addPersonResponse"&gt;<br />&lt;part name="result" type="xsd:int"/&gt;<br />&lt;/message&gt;<br />&lt;/definitions&gt;<br /><br />在 Types 區段的 Gender &lt;element&gt; 中，內嵌著一個匿名的列舉類型，其值可以是「Male」或「Female」。然後在「addPerson」的 &lt;message&gt; 中，再使用元素屬性 (不用類型屬性) 參照該元素。<br /><br />若欲關連特定類型至 &lt;part&gt;，使用「元素」與「類型」屬性有何不同？若使用「類型」屬性，part 可描述成能採取數種類型 (就像變數一樣)；但若使用「元素」屬性，便不能這麼做。請參考下列範例的說明。<br /><br />&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;definitions ?&gt;<br />&lt;types&gt;<br />&lt;schema targetNamespace="someNamespace" <br />xmlns:typens="someNamespace"&gt;<br />&lt;xsd:complexType name="PERSON"&gt;<br />&lt;xsd:sequence&gt;<br />&lt;xsd:element name="firstName" type="xsd:string"/&gt;<br />&lt;xsd:element name="lastName" type="xsd:string"/&gt;<br />&lt;xsd:element name="ageInYears" type="xsd:int"/&gt;<br />&lt;xsd:element name="weightInLbs" type="xsd:float"/&gt;<br />&lt;xsd:element name="heightInInches" type="xsd:float"/&gt;<br />&lt;/xsd:sequence&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;xsd:complexType name="femalePerson"&gt;<br />&lt;xsd:complexContent&gt;<br />&lt;xsd:extension base="typens:PERSON" &gt;<br />&lt;xsd:element name="favoriteLipstick" type="xsd:string" /&gt;<br />&lt;/xsd:extension&gt;<br />&lt;/xsd:complexContent&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;xsd:complexType name="malePerson"&gt;<br />&lt;xsd:complexContent&gt;<br />&lt;xsd:extension base="typens:PERSON" &gt;<br />&lt;xsd:element name="favoriteShavingLotion" type="xsd:string" /&gt;<br />&lt;/xsd:extension&gt;<br />&lt;/xsd:complexContent&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;xsd:complexType name="maleOrFemalePerson"&gt;<br />&lt;xsd:choice&gt;<br />&lt;xsd:element name="fArg" type="typens:femalePerson" &gt;<br />&lt;xsd:element name="mArg" type="typens:malePerson" /&gt;<br />&lt;/xsd:choice&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;/schema&gt;<br />&lt;/types&gt;<br /><br />&lt;message name="addPerson"&gt;<br />&lt;part name="person" type="typens:maleOrFemalePerson"/&gt;<br />&lt;/message&gt;<br /><br />&lt;message name="addPersonResponse"&gt;<br />&lt;part name="result" type="xsd:int"/&gt;<br />&lt;/message&gt;<br /><br />&lt;/definitions&gt;<br /><br />此範例也說明了副檔名的衍生用法。「femalePerson」與「malePerson」兩者，都是衍生自「PERSON」。它們都各有一個額外的元素：「femalePerson」的「favoriteLipstick」以及「malePerson」的「favoriteShavingLotion」。使用 &lt;choice&gt; 的 construct，這兩個衍生類型又可結合成一個複雜類型「maleOrFemalePerson」。最後，在「addPerson」的 &lt;message&gt; 中，此結合類型又可供「person」的 &lt;part&gt; 參照。而此 &lt;part&gt; 或參數，可以是「femalePerson」或「malePerson」。<br /><br />陣列<br />XSD 可提供 &lt;list&gt; construct，以宣告空白所分隔的項目陣列。但是，SOAP 並不使用 XSD 清單為陣列編碼；而是為陣列定義自己的類型，即「SOAP-ENC:Array」。下列範例說明，如何為單一維度的整數陣列，依其法則導出此種類型：<br /><br />&lt;xsd:complexType name="ArrayOfInt"&gt;<br />&lt;xsd:complexContent&gt;<br />&lt;xsd:restriction base="soapenc:Array"&gt;<br />&lt;attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:int[]"/&gt;<br />&lt;/xsd:restriction&gt;<br />&lt;/xsd:complexContent&gt;<br />&lt;/xsd:complexType&gt;<br /><br />只要使用導出限制的方式，即可從 soapenc:Array 宣告新的複雜類型。接著便可宣告此複雜類型的屬性：arrayType。參照「soapenc:arrayType」實際上即是 arrayType 屬性的宣告，其方式如下：<br /><br />&lt;xsd:attribute name="arrayType" type="xsd:string"/&gt;<br /><br />然後，wsdl:arrayType 屬性值，可決定每個陣列成員的類型。陣列項目也可以是複雜類型：<br /><br />&lt;xsd:complexType name="ArrayOfPERSON"&gt;<br />&lt;xsd:complexContent&gt;<br />&lt;xsd:restriction base="soapenc:Array"&gt;<br />&lt;attribute ref="soapenc:arrayType" <br />wsdl:arrayType="typens:PERSON[]"/&gt;<br />&lt;/xsd:restriction&gt;<br />&lt;/xsd:complexContent&gt;<br />&lt;/xsd:complexType&gt;<br /><br />WSDL 的要求是，陣列的類型名稱必須是，「ArrayOf」與陣列項目類型的的串連 (concatenation)。也因此，單從名稱即可得知，「ArrayOfPERSON」是 PERSON struct 的陣列。在下例中，只要使用 ArrayOfPERSON 宣告一個 &lt;message&gt;，即可新增多個 PERSON：<br /><br />&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;definitions ?&gt;<br />&lt;types&gt;<br />&lt;schema targetNamespace="someNamespace" <br />xmlns:typens="someNamespace" &gt;<br />&lt;xsd:complexType name="PERSON"&gt;<br />&lt;xsd:sequence&gt;<br />&lt;xsd:element name="firstName" type="xsd:string"/&gt;<br />&lt;xsd:element name="lastName" type="xsd:string"/&gt;<br />&lt;xsd:element name="ageInYears" type="xsd:int"/&gt;<br />&lt;xsd:element name="weightInLbs" type="xsd:float"/&gt;<br />&lt;xsd:element name="heightInInches" type="xsd:float"/&gt;<br />&lt;/xsd:sequence&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;xsd:complexType name="ArrayOfPERSON"&gt;<br />&lt;xsd:complexContent&gt;<br />&lt;xsd:restriction base="soapenc:Array"&gt;<br />&lt;attribute ref="soapenc:arrayType" <br />wsdl:arrayType="typens:PERSON[]"/&gt;<br />&lt;/xsd:restriction&gt;<br />&lt;/xsd:complexContent&gt;<br />&lt;/xsd:complexType&gt;<br />&lt;/schema&gt;<br />&lt;/types&gt;<br /><br />&lt;message name="addPersons"&gt;<br />&lt;part name="person" type="typens:ArrayOfPERSON"/&gt;<br />&lt;/message&gt;<br /><br />&lt;message name="addPersonResponse"&gt;<br />&lt;part name="result" type="xsd:int"/&gt;<br />&lt;/message&gt;<br /><br />&lt;/definitions&gt;<br /><br />&lt;portType&gt; 與 &lt;operation&gt; 元素<br />PortType 可在抽象中，定義多種作業。PortType 中的作業元素，可定義呼叫所有 PortType 方法的語法。每個作業元素都會宣告，方法的名稱、參數 (使用 &lt;message&gt; 元素)、類型 (每個 &lt;message&gt; 中所宣告的 &lt;part&gt; 元素)。<br /><br />在 WSDL 文件中，可有多個 &lt;portType&gt; 元素。每個 &lt;portType&gt; 元素，群組化多個相關作業的方式，與 COM 介面群組化方法的方式非常類似。<br /><br />在一個 &lt;operation&gt; 元素中，最多可有一個 &lt;input&gt; 元素、一個 &lt;output&gt; 元素、與一個 &lt;fault&gt; 元素。這三個元素都各有一個名稱與訊息屬性。<br /><br />在 &lt;input&gt;、&lt;output&gt;、與 &lt;fault&gt; 元素中使用名稱屬性的目的為何？原來是為了，區別具相同名稱 (多載) 的兩項作業。例如，下列兩個 C 函數，即具有相同的名稱，但不同的參數。<br /><br />void foo(int arg);<br />void foo(string arg);<br /><br />使用 WSDL 時，這種多載的表達方式如下：<br /><br />&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;definitions name="fooDescription"<br />targetNamespace="http://tempuri.org/wsdl/"<br />xmlns:wsdlns="http://tempuri.org/wsdl/"<br />xmlns:typens="http://tempuri.org/xsd"<br />xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"<br />xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-<br />extension"<br />xmlns="http://schemas.xmlsoap.org/wsdl/"&gt;<br />&lt;types&gt;<br />&lt;schema targetNamespace="http://tempuri.org/xsd"<br />xmlns="http://www.w3.org/2001/XMLSchema" <br />xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"<br />xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"<br />elementFormDefault="qualified" &gt;<br />&lt;/schema&gt;<br />&lt;/types&gt;<br /><br />&lt;message name="foo1"&gt;<br />&lt;part name="arg" type="xsd:int"/&gt;<br />&lt;/message&gt;<br /><br />&lt;message name="foo2"&gt;<br />&lt;part name="arg" type="xsd:string"/&gt;<br />&lt;/message&gt;<br /><br />&lt;portType name="fooSamplePortType"&gt;<br />&lt;operation name="foo" parameterOrder="arg " &gt;<br />&lt;input name="foo1" message="wsdlns:foo1"/&gt;<br />&lt;/operation&gt;<br />&lt;operation name="foo" parameterOrder="arg " &gt;<br />&lt;input name="foo2" message="wsdlns:foo2"/&gt;<br />&lt;/operation&gt;<br />&lt;/portType&gt;<br /><br />&lt;binding name="fooSampleBinding" type="wsdlns:fooSamplePortType"&gt;<br />&lt;stk:binding preferredEncoding="UTF-8" /&gt;<br />&lt;soap:binding style="rpc" <br />transport="http://schemas.xmlsoap.org/soap/http"/&gt;<br />&lt;operation name="foo"&gt;<br />&lt;soap:operation soapAction="http://tempuri.org/action/foo1"/&gt;<br />&lt;input name="foo1"&gt;<br />&lt;soap:body use="encoded" namespace="http://tempuri.org/message/" <br />encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br />&lt;operation name="foo"&gt;<br />&lt;soap:operation soapAction="http://tempuri.org/action/foo2"/&gt;<br />&lt;input name="foo2"&gt;<br />&lt;soap:body use="encoded" <br />namespace="http://tempuri.org/message/" <br />encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" <br />/&gt;<br />&lt;/input&gt;<br />&lt;/operation&gt;<br />&lt;/binding&gt;<br /><br />&lt;service name="FOOService"&gt;<br />&lt;port name="fooSamplePort" binding="fooSampleBinding"&gt;<br />&lt;soap:address <br />location="http://carlos:8080/fooService/foo.asp"/&gt;<br />&lt;/port&gt;<br />&lt;/service&gt;<br />&lt;/definitions&gt;</font>
		</p>
<img src ="http://www.blogjava.net/esoa/aggbug/86908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-12-11 14:59 <a href="http://www.blogjava.net/esoa/articles/86908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WSDL文件详解(1)</title><link>http://www.blogjava.net/esoa/articles/86904.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Mon, 11 Dec 2006 06:48:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/86904.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/86904.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/86904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/86904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/86904.html</trackback:ping><description><![CDATA[
		<p>
				<font face="宋体">摘要：只要使用 WSDL，即可以真正不受語言與平台限制的方式，自動為網路服務產生 Proxy。(列印共 28 頁)<br /><br />內容<br />使用 WSDL 的原因<br />WSDL 文件結構<br />WSDL 範例檔案<br />命名空間<br />SOAP 訊息<br />WSDL 類型與訊息區段中的 XML 結構描述<br />&lt;portType&gt; 與 &lt;operation&gt; 元素<br />&lt;binding&gt; 與 &lt;operation&gt; 元素<br />文件樣式繫結<br />&lt;service&gt; 與 &lt;port&gt; 元素<br />總結<br />資源<br /><br />使用 WSDL 的原因<br />網路通訊協定之類的標準，到底是某當權機構強制施行的；或是，人們真的認為，確實遵守的優點遠勝於必須付出的代價？歷來所提出的標準，許多都無疾而終。有時候，從未被大眾所使用的標準，法律或政府規定還是硬要使用：好比說，Ada 程式語言。<br /><br />我相信，遵守標準所能獲得的優點，才是使標準普及的原因。例如，鐵路服務的重點是，即使不同公司所建造的列車軌道，也可以接駁在一起；也就是說，不同公司的產品必須能整合使用。因此，幾家廠商便共同推出了 SOAP 這個標準。WSDL (Web Services Description Language，網路服務描述語言) 可輕易將網路服務提供廠商與服務的使用者結合起來，輕鬆獲取 SOAP 的優點。不同公司所建造的列車軌道比較容易整合；畢竟，必須同意的標準不過是兩條鐵軌之間的距離而已。但對網路服務而言，情況則複雜得多了。首先必須取得的共識是，指定介面的標準格式。<br /><br />有個論點一直認為，SOAP 並不需要介面描述語言。若 SOAP 純粹是溝通內容的標準，那麼它需要的便是描述該內容的語言。SOAP 訊息確實可傳遞類型資訊，也因此 SOAP 允許以動態的方式決定類型。但除非知道函數的名稱、參數、與類型，否則根本無法正確呼叫任何函數。若不使用 WSDL，還是可以從所提供的文件或檢查線路訊息，來確定呼叫的語法。但這兩種方式都需要人力介入，也因此可能在過程中出現錯誤。若使用 WSDL，即可以真正不受語言與平台限制的方式，自動為網路服務產生 Proxy。類似 CORBA 或 COM 的 IDL 檔案，WSDL 檔案也是一種客戶端與伺服端之間的合約。<br /><br />請注意，雖然 WSDL 的設計目的是，對 SOAP 以外的通訊協定顯示繫結；但本文的主旨則是在 HTTP 上與 SOAP 有關連的 WSDL。而且雖然目前 SOAP 的主要用途是遠端程序或函數呼叫，但 WSDL 已經可以在 SOAP 下，指定傳輸的文件。WSDL 1.1 已經以 Note (通知書) 的方式 (請參閱 http://www.w3.org/TR/wsdl.html)，提交至 W3C 。<br /><br />WSDL 文件結構<br />若欲瞭解任何 XML 文件，區塊圖是很有助益的。下圖說明 WSDL 的結構；它是一種 XML 文件，可顯示 WSDL 文件五個組成區段之間的關係。<br /><br />WSDL 文件可分成兩個區段群組。上群組是由抽象定義 (Abstract Definitions) 所組成；而下群組則是由具體定義 (Concrete Descriptions) 所組成。抽象區段定義 SOAP 訊息的方式是，排除平台與語言的限制；因此它們不含任何電腦或語言特有的元素。如此一來，不同的網站皆可實作它所定義的服務。諸如序列化等網站特有的資訊，則交由含具體描述的下區段處理。<br /><br />抽象定義<br />Types (類型)<br />不受電腦與語言限制的類型定義。 <br />Messages (訊息)<br />內含函數參數 (輸入與輸出分離) 或文件描述。 <br />PortTypes (埠類型)<br />根據 Messages 區段中的訊息定義，說明函數簽章 (作業名稱、輸入參數、輸出參數)。 <br />具體定義<br />Bindings (繫結)<br />在 PortTypes 區段中，指定每個作業的繫結。 <br />Services (服務)<br />指定每個繫結的傳輸埠位址。 <br />在下圖中，箭頭連接代表，在文件的不同區段之間有關聯性存在。點與箭頭連接代表「參照」或「使用」關係。雙箭頭連接代表「修改 (modifier)」關係。3-D 箭頭連接代表「包含 (contains)」關係。因此，Messages 區段使用 Types 區段的定義；PortTypes 區段使用 Messages 區段的定義；Bindings 區段參照 PortTypes 區段；Services 區段參照 Bindings 區段。PortTypes 與 Bindings 區段內含作業元素，而 Services 區段則內含埠元素。Bindings 區段中的作業元素，會修改或進一步說明 PortTypes 區段中的作業元素。<br /><br />以此為基礎，本文將使用標準 XML 技術，說明 WSDL 文件。「元素」一詞是指 XML 元素，而「屬性」一詞則是指元素屬性。因此：<br /><br />&lt;element attribute="attribute-value"&gt;contents&lt;/element&gt;<br /><br />內容可以遞迴的方式，由一個以上的元素組成。根元素是最頂端的元素，文件中其它所有元素皆歸在其下。子元素永遠附屬於其它的父元素。<br /><br />請注意，只可以有一個 Types 區段，甚或根本沒有此區段。其它所有區段可以有零、一、或多個父元素。例如，Messages 區段可以有零、或多個 &lt;message&gt; 元素。WSDL 結構描述規定，所有區段必須依指定順序排列：匯入、類型、訊息、portType、繫結、與服務。每個抽象區段可能各自位於不同的檔案，並分別匯入至主文件中。<br /><br /><br /><br />[圖 1] 抽象與具體定義<br /><br />WSDL 範例檔案<br />現在請一同深入探討 WSDL 範例檔案，以檢視其結構與咦鞣绞健Ｕ堄浀眠@是一個非常簡單的 WSDL 文件範例。其目的僅在解說最明顯的功能。下列各區段皆有更詳實的討論。<br /><br />&lt;?xml version="1.0" encoding="UTF-8" ?&gt;<br />&lt;definitions name="FooSample"<br />targetNamespace="http://tempuri.org/wsdl/"<br />xmlns:wsdlns="http://tempuri.org/wsdl/"<br />xmlns:typens="http://tempuri.org/xsd"<br />xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"<br />xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension"<br />xmlns="http://schemas.xmlsoap.org/wsdl/"&gt;<br /><br />&lt;types&gt;<br />&lt;schema targetNamespace="http://tempuri.org/xsd" <br />xmlns="http://www.w3.org/2001/XMLSchema" <br />xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" <br />xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"<br />elementFormDefault="qualified" &gt;<br />&lt;/schema&gt;<br />&lt;/types&gt;<br /><br />&lt;message name="Simple.foo"&gt;<br />&lt;part name="arg" type="xsd:int"/&gt;<br />&lt;/message&gt;<br /><br />&lt;message name="Simple.fooResponse"&gt;<br />&lt;part name="result" type="xsd:int"/&gt;<br />&lt;/message&gt;<br /><br />&lt;portType name="SimplePortType"&gt;<br />&lt;operation name="foo" parameterOrder="arg" &gt;<br />&lt;input message="wsdlns:Simple.foo"/&gt;<br />&lt;output message="wsdlns:Simple.fooResponse"/&gt;<br />&lt;/operation&gt;<br />&lt;/portType&gt;<br /><br />&lt;binding name="SimpleBinding" type="wsdlns:SimplePortType"&gt;<br />&lt;stk:binding preferredEncoding="UTF-8" /&gt;<br />&lt;soap:binding style="rpc" <br />transport="http://schemas.xmlsoap.org/soap/http"/&gt;<br />&lt;operation name="foo"&gt;<br />&lt;soap:operation<br />soapAction="http://tempuri.org/action/Simple.foo"/&gt;<br />&lt;input&gt;<br />&lt;soap:body use="encoded" namespace="http://tempuri.org/message/" <br />encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /&gt;<br />&lt;/input&gt;<br />&lt;output&gt;<br />&lt;soap:body use="encoded" namespace="http://tempuri.org/message/" <br />encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /&gt;<br />&lt;/output&gt;<br />&lt;/operation&gt;<br />&lt;/binding&gt;<br /><br />&lt;service name="FOOSAMPLEService"&gt;<br />&lt;port name="SimplePort" binding="wsdlns:SimpleBinding"&gt;<br />&lt;soap:address location="http://carlos:8080/FooSample/FooSample.asp"/&gt;<br />&lt;/port&gt;<br />&lt;/service&gt;<br />&lt;/definitions&gt;<br /><br />下列為此範例文件的大略說明。稍後，會就每個區段詳細討論。<br /><br />第一行宣告，本文件為 XML。雖然非是必要，但它可協助 XML 剖析器決定，應該剖析此 WSDL 檔案，或發出錯誤訊號。第二行是 WSDL 文件中的根元素：&lt;definitions&gt;。有幾個命名空間屬性 (命名空間宣告)，附屬於此根元素以及 &lt;types&gt; 元素的 &lt;schema&gt; 子元素中。<br /><br />&lt;types&gt; 元素是由 Types 區段組成。若無資料類型須要宣告，則此區段可以省略。在範例 WSDL 中，並無應用程式專屬的類型須要宣告，但還是使用 Types 區段，以宣告本文件中結構描述的命名空間。<br /><br />&lt;message&gt; 元素是由 Messages 區段所組成。若將作業視為函數，則 &lt;message&gt; 元素可將參數定義至該函數。&lt;message&gt; 元素中的每個 &lt;part&gt; 子元素，都對應一個參數。請將參數定義輸入至單一的 &lt;message&gt; 元素之中，並與位於自己 &lt;message&gt; 元素中的輸出參數分開。同時是輸入與輸出的參數，在輸入與輸出 &lt;message&gt; 元素中，各有與自己相對應的 &lt;part&gt; 元素。根據慣例，輸出 &lt;message&gt; 元素的名稱，如同「fooResponse」，會以「Response」結束。如同函數參數需有名稱與類型一樣，每個 &lt;part&gt; 元素也都有名稱與類型屬性。<br /><br />若用於文件交換，WSDL 可使用 &lt;message&gt; 元素，說明交換的文件。<br /><br />&lt;part&gt; 元素的類型可以是，XSD 基礎類型、SOAP 定義類型 (soapenc)、WSDL 定義類型 (wsdl)、或 Types 區段的定義類型。<br /><br />在 PortTypes 區段中，可以有零、一、或更多個 &lt;portType&gt; 元素。由於抽象的 PortType 定義，可置於不同的檔案中；因此在 WSDL 檔案中，可以有零個 &lt;portType&gt; 元素。在上面的範例中，即只有一個 &lt;portType&gt; 元素。杖缢姡?lt;portType&gt; 元素可在 &lt;operation&gt; 元素中，定義一或多個作業。此範例僅顯示一個名為「foo」的 &lt;operation&gt; 元素。此名稱應與函數名稱相同。&lt;operation&gt; 元素可有一、二、或三個子元素：即 &lt;input&gt;、&lt;output&gt; 與 &lt;fault&gt; 元素。每個 &lt;input&gt; 與 &lt;output&gt; 元素中的訊息屬性，都會參照 Messages 區段中的相關 &lt;message&gt; 元素。因此，範例中的整個 &lt;portType&gt; 元素，相當於下列的 C 函數宣告：<br /><br />int foo(int arg);<br /><br />此範例正足以說明，相較於 C，XML 是多麼冗長的語言。 (包括 &lt;message&gt; 元素在內，此範例共使用 12 行的 XML 進行函數宣告；而相同的動作， C 只要一行即可。)<br /><br />Bindings 區段可有零、一或多個 &lt;binding&gt; 元素。而其目的則是，指定每個 &lt;operation&gt; 呼叫與回應，在線上傳送的方式。Services 區段也可有零、一或多個 &lt;service&gt; 元素。它所含的 &lt;port&gt; 元素，每個都參照 Bindings 區段中的一個 &lt;binding&gt; 元素。Bindings 與 Services 區段都是由，WSDL 文件的具體描述所組成。<br /><br />命名空間<br />在根元素 &lt;definitions&gt; 與子元素 &lt;schema&gt; 中，都有命名空間屬性：<br /><br />&lt;definitions name="FooSample"<br />targetNamespace="http://tempuri.org/wsdl/"<br />xmlns:wsdlns="http://tempuri.org/wsdl/"<br />xmlns:typens="http://tempuri.org/xsd"<br />xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"<br />xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension"<br />xmlns="http://schemas.xmlsoap.org/wsdl/"&gt;<br /><br />&lt;types&gt;<br />&lt;schema targetNamespace="http://tempuri.org/xsd" <br />xmlns="http://www.w3.org/2001/XMLSchema" <br />xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" <br />xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"<br />elementFormDefault="qualified" &gt;<br />&lt;/schema&gt;<br />&lt;/types&gt;<br /><br />每個命名空間屬性，都會為命名空間宣告一個速記法，以便在文件中使用。例如，「xmlns:xsd」可定義一個速記法 (xsd)，代表命名空間 http://www.w3.org/2001/XMLSchema。如此一來，稍後即可在文件中參照此命名空間；其方式很簡單，只要在名稱前嵌入字首「xsd」，則「xsd:int」即成為合格的類型名稱。一般的領域設定規則，皆可套用至此速記字首。也就是說，在一個元素中所定義的字首，僅在該元素中使用。<br /><br />使用命名空間的原因何在？命名空間的目的在避免命名衝突。若我建立了一個網路服務，其 WSDL 檔案中含有一個名為「foo」的元素，而您想要將我的網路服務，與另一個互補性的服務結合起來使用；假若沒有使用命名空間，則另一個網路服務，在其 WSDL 檔案中，便絕對不能使用「foo」這個名稱。除非在兩者的執行個體中，都是指完全相同的東西，否則這兩個服務不可以使用相同的名稱。但若使用兩個不同的命名空間，則我網路服務的「foo」所代表的意義，便與另一個網路服務的「foo」不同。在客戶端，您便必須以嵌入字首 (prefixing 或 qualifying) 的方式，參照我的「foo」。例如，若我宣告 http://www.infotects.com/fooService 的速記法是 carlos，則 http://www.infotects.com/fooService#foo 這個完全合格的名稱，可以等於「carlos:foo」。請注意，若使用 URI 作為命名空間，不但可確保其獨特性，更可允許在文件中使用定址器。URI 所指向的位址，不必對應真正的網路位址。也可以使用 GUID 代替或補充 URI。例如，GUID「335DB901-D44A-11D4-A96E-0080AD76435D」即是個有效的命名空間指示項。<br /><br />元素中所宣告的所有名稱，都附屬於 targetNamespace 屬性所宣告的命名空間之下。在 WSDL 範例檔案中，代表 &lt;definitions&gt; 的 targetNamespace 是 http://tempuri.org/wsdl。它所代表的意義是，在此 WSDL 文件中宣告的所有名稱，都附屬於此命名空間。由於 &lt;schema&gt; 元素有它自己的 targetNamespace 屬性，且其值為 http://tempuri.org/xsd；所以在此 &lt;schema&gt; 元素中定義的所有名稱，都是屬於此命名空間，而不屬於主目標命名空間。<br /><br />下一行程式碼位於 &lt;schema&gt; 元素中，它所宣告的是預設的命名空間。結構中所有無嵌入字首 (unqualified ) 的名稱，都屬於此命名空間。<br /><br />xmlns="http://www.w3.org/2001/XMLSchema" <br /><br />SOAP 訊息<br />對使用 WSDL 檔案的客戶端與伺服端而言，它所代表的意義之一是，可決定線上傳送的內容。雖然 SOAP 使用的是，諸如 IP 與 HTTP 等低層次的通訊協定，但此應用程式卻可決定，特定客戶端與特定伺服端之間所使用的高層次通訊協定。換句話說，若以「echoInt」作業為例，使用回波傳回輸入整數，則參數總計、每個參數的類型、與參數傳過線路的方式 (序列化) 等，便會構成一個應用程式特有的通訊協定。指定這類通訊協定的方式很多，但我認為使用 WSDL 才是最佳的方式。若就此觀點而言，WSDL 便不只是一種「介面合約」，它更是一種通訊協定指定語言。若超出了諸如 IP 與 HTTP 等固定通訊協定的範圍，進入應用程式專屬通訊協定的領域，WSDL 正好符合我們所需。<br /><br />WSDL 可以指定，SOAP 訊息是否符合 rpc 或文件樣式。正如範例中所使用的一樣，rpc 樣式訊息的外觀就像是，一個有零或多個參數的函數呼叫。文件樣式訊息則較扁平 (flatter) 且不需要那麼多的巢狀階層。下列 XML 訊息的傳送與接收，是使用 MS SOAP Toolkit 2.0 (MSTK2) 的 SoapClient 物件，剖析 WSDL 範例檔案的結果。<br /><br />自客戶端執行函數呼叫「foo(5131953)」：<br /><br />&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;<br />&lt;SOAP-ENV:Envelope <br />SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" <br />xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"&gt;<br />&lt;SOAP-ENV:Body&gt;<br />&lt;m:foo xmlns:m="http://tempuri.org/message/"&gt;<br />&lt;arg&gt;5131953&lt;/arg&gt;<br />&lt;/m:foo&gt;<br />&lt;/SOAP-ENV:Body&gt;<br />&lt;/SOAP-ENV:Envelope&gt;<br /><br />伺服端所接收到的 (回應)：<br /><br />&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;<br />&lt;SOAP-ENV:Envelope <br />SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" <br />xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"&gt;<br />&lt;SOAP-ENV:Body&gt;<br />&lt;SOAPSDK1:fooResponse xmlns:SOAPSDK1="http://tempuri.org/message/"&gt;<br />&lt;result&gt;5131953&lt;/result&gt;<br />&lt;/SOAPSDK1:fooResponse&gt;<br />&lt;/SOAP-ENV:Body&gt;<br />&lt;/SOAP-ENV:Envelope&gt;<br /><br />此函數呼叫訊息與其回應，都是正確有效的 XML。SOAP 訊息是由 &lt;Envelope&gt; 元素所組成，其中含有一個選擇性的 &lt;Header&gt; 元素，與至少一個的 &lt;body&gt; 元素。傳送與接收訊息兩者，在主 &lt;Envelope&gt; 元素中，都有只一個 &lt;Body&gt; 元素。rpc 函數呼叫訊息的主體，有一個依作業名稱「foo」命名的元素，而回應主體中則有一個名為「fooResponse」元素。這個 foo 元素有個如範例 WSDL 所示的單一引數，其名稱為 &lt;arg&gt;。同樣地，fooResponse 也有一個 &lt;result&gt;。在此處重複出現的 WSDL Bindings 區段中，請注意 encodingStyle、信封、與訊息命名空間的指定方式。<br /><br />&lt;binding name="SimpleBinding" type="wsdlns:SimplePortType"&gt;<br />&lt;stk:binding preferredEncoding="UTF-8" /&gt;<br />&lt;soap:binding style="rpc" <br />transport="http://schemas.xmlsoap.org/soap/http"/&gt;<br />&lt;operation name="foo"&gt;<br />&lt;soap:operation<br />soapAction="http://tempuri.org/action/Simple.foo"/&gt;<br />&lt;input&gt;<br />&lt;soap:body use="encoded" <br />namespace="http://tempuri.org/message/" <br />encodingStyle=<br />"http://schemas.xmlsoap.org/soap/encoding/" /&gt;<br />&lt;/input&gt;<br />&lt;output&gt;<br />&lt;soap:body use="encoded" <br />namespace="http://tempuri.org/message/" <br />encodingStyle=<br />"http://schemas.xmlsoap.org/soap/encoding/" /&gt;<br />&lt;/output&gt;<br />&lt;/operation&gt;<br />&lt;/binding&gt;<br /></font>
		</p>
<img src ="http://www.blogjava.net/esoa/aggbug/86904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-12-11 14:48 <a href="http://www.blogjava.net/esoa/articles/86904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WSDL规则与示例(1)</title><link>http://www.blogjava.net/esoa/articles/86902.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Mon, 11 Dec 2006 06:46:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/86902.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/86902.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/86902.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/86902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/86902.html</trackback:ping><description><![CDATA[
		<p>首先看看一段简单的JAVA代码,我们用它作为WSDL的服务实现代码:<br />public class Test<br />{<br />  public String echo(String u){<br />    return "Hello " + u;<br />  }<br />}<br />然后看看用它导出的WSDL:<br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;wsdl:definitions targetNamespace="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" xmlns="<a href="http://schemas.xmlsoap.org/wsdl/">http://schemas.xmlsoap.org/wsdl/</a>" xmlns:apachesoap="<a href="http://xml.apache.org/xml-soap">http://xml.apache.org/xml-soap</a>" xmlns:impl="<a href="http://businessengine.hongsoft.com-impl/">http://businessEngine.hongsoft.com-impl</a>" xmlns:intf="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" xmlns:soapenc="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" xmlns:wsdl="<a href="http://schemas.xmlsoap.org/wsdl/">http://schemas.xmlsoap.org/wsdl/</a>" xmlns:wsdlsoap="<a href="http://schemas.xmlsoap.org/wsdl/soap/">http://schemas.xmlsoap.org/wsdl/soap/</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>"&gt;<br />   &lt;wsdl:types/&gt;//我们没有自定义的类型</p>
		<p>   &lt;wsdl:message name="echoResponse"&gt;//返回的消息</p>
		<p>      &lt;wsdl:part name="echoReturn" type="xsd:string"/&gt;</p>
		<p>   &lt;/wsdl:message&gt;</p>
		<p>   &lt;wsdl:message name="echoRequest"&gt;//请求的消息</p>
		<p>      &lt;wsdl:part name="u" type="xsd:string"/&gt;</p>
		<p>   &lt;/wsdl:message&gt;</p>
		<p>   &lt;wsdl:portType name="Test"&gt;//一个portType可以看着一个类</p>
		<p>      &lt;wsdl:operation name="echo" parameterOrder="u"&gt;//一个operation就是一个方法</p>
		<p>         &lt;wsdl:input message="intf:echoRequest" name="echoRequest"/&gt;</p>
		<p>         &lt;wsdl:output message="intf:echoResponse" name="echoResponse"/&gt;</p>
		<p>      &lt;/wsdl:operation&gt;</p>
		<p>   &lt;/wsdl:portType&gt;</p>
		<p>   &lt;wsdl:binding name="TestSoapBinding" type="intf:Test"&gt;<br />      //下面指定消息封装方式</p>
		<p>      &lt;wsdlsoap:binding style="rpc" transport="<a href="http://schemas.xmlsoap.org/soap/http" ?="">http://schemas.xmlsoap.org/soap/http"/</a>&gt;<br />      //下面将WSDL描述与具体实现进行绑定,这里采用SOAP方式</p>
		<p>      &lt;wsdl:operation name="echo"&gt;</p>
		<p>         &lt;wsdlsoap:operation soapAction=""/&gt;</p>
		<p>         &lt;wsdl:input name="echoRequest"&gt;</p>
		<p>            &lt;wsdlsoap:body encodingStyle="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" namespace="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" use="encoded"/&gt;</p>
		<p>         &lt;/wsdl:input&gt;</p>
		<p>         &lt;wsdl:output name="echoResponse"&gt;</p>
		<p>            &lt;wsdlsoap:body encodingStyle="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" namespace="<a href="http://businessengine.hongsoft.com/">http://businessEngine.hongsoft.com</a>" use="encoded"/&gt;</p>
		<p>         &lt;/wsdl:output&gt;</p>
		<p>      &lt;/wsdl:operation&gt;</p>
		<p>   &lt;/wsdl:binding&gt;<br />   //下面将发布的服务与前面的SOAP绑定进行关联</p>
		<p>   &lt;wsdl:service name="TestService"&gt;</p>
		<p>      &lt;wsdl:port binding="intf:TestSoapBinding" name="Test"&gt;</p>
		<p>         &lt;wsdlsoap:address location="<a href="http://localhost:8080/hongsoft/services/Test" ?="">http://localhost:8080/hongsoft/services/Test"/</a>&gt;</p>
		<p>      &lt;/wsdl:port&gt;</p>
		<p>   &lt;/wsdl:service&gt;</p>
		<p>&lt;/wsdl:definitions&gt;</p>
<img src ="http://www.blogjava.net/esoa/aggbug/86902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-12-11 14:46 <a href="http://www.blogjava.net/esoa/articles/86902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WSDL文件示例+相关链接</title><link>http://www.blogjava.net/esoa/articles/86901.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Mon, 11 Dec 2006 06:44:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/86901.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/86901.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/86901.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/86901.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/86901.html</trackback:ping><description><![CDATA[
		<strong>WSDL文件示例<br /><br /></strong>　　让我们来研究一下WSDL文件，看看它的结构，以及如何工作。请注意这是一个非常简单的WSDL文档实例。我们的意图只是说明它最显著的特征。以下的内容中包括更加详细的讨论。<br /><br /><table width="629" align="center" bgcolor="#ebe9eb" border="0"><tbody><tr><td>＜?xml version="1.0" encoding="UTF-8" ?＞<br />＜definitions name="FooSample"<br />　targetNamespace="http://tempuri.org/wsdl/"<br />　xmlns:wsdlns="http://tempuri.org/wsdl/"<br />　xmlns:typens="http://tempuri.org/xsd"<br />　xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />　xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"<br />　xmlns:stk="http://schemas.microsoft.com/soap-toolkit/wsdl-extension"<br />　xmlns="http://schemas.xmlsoap.org/wsdl/"＞<br /><br />＜types＞<br />＜schema targetNamespace="http://tempuri.org/xsd" <br />　　xmlns="http://www.w3.org/2001/XMLSchema" <br />　　xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" <br />　　xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"<br />　　elementFormDefault="qualified" ＞<br />＜/schema＞<br />＜/types＞<br /><br />＜message name="Simple.foo"＞<br />　＜part name="arg" type="xsd:int"/＞<br />＜/message＞<br /><br />＜message name="Simple.fooResponse"＞<br />　＜part name="result" type="xsd:int"/＞<br />＜/message＞<br /><br />＜portType name="SimplePortType"＞<br />　＜operation name="foo" parameterOrder="arg" ＞<br />　　＜input message="wsdlns:Simple.foo"/＞<br />　　＜output message="wsdlns:Simple.fooResponse"/＞<br />　＜/operation＞<br />＜/portType＞<br /><br />＜binding name="SimpleBinding" type="wsdlns:SimplePortType"＞<br />　＜stk:binding preferredEncoding="UTF-8" /＞<br />　＜soap:binding style="rpc" <br />　　transport="http://schemas.xmlsoap.org/soap/http"/＞<br />　＜operation name="foo"＞<br />　　＜soap:operation soapAction="http://tempuri.org/action/Simple.foo"/＞<br />　　＜input＞<br />　　　＜soap:body use="encoded" namespace="http://tempuri.org/message/" <br />　　　　encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /＞<br />　　＜/input＞<br />　　＜output＞<br />　　　＜soap:body use="encoded" namespace="http://tempuri.org/message/" <br />　　　　encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /＞<br />　　＜/output＞<br />　＜/operation＞<br />＜/binding＞<br /><br />＜service name="FOOSAMPLEService"＞<br />　＜port name="SimplePort" binding="wsdlns:SimpleBinding"＞<br />　　＜soap:address location="http://carlos:8080/FooSample/FooSample.asp"/＞<br />　＜/port＞<br />＜/service＞<br />＜/definitions＞</td></tr></tbody></table><br />　　以下是该实例文档的总述：稍后我将详细讨论每一部分的细节。<br /><br />　　第一行申明该文档是XML。尽管这并不是必需的，但它有助于XML解析器决定是否解析WSDL文件或只是报错。第二行是WSDL文档的根元素：＜definitions＞。一些属性附属于根元素，就像＜schema＞子元素对于＜types＞元素。<br /><br />　　＜types＞元素包含了Types栏。如果没有需要声明的数据类型，这栏可以缺省。在WSDL范例中，没有应用程序特定的types声明，但我仍然使用了Types栏，只是为了声明schema namespaces。<br /><br />　　＜message＞元素包含了Messages栏。如果我们把操作看作函数，＜message＞元素定义了那个函数的参数。＜message＞元素中的每个＜part＞子元素都和某个参数相符。输入参数在＜message＞元素中定义，与输出参数相隔离--输出参数有自己的＜message＞元素。兼作输入、输出的参数在输入输出的＜message＞元素中有它们相应的＜part＞元素。输出＜message＞元素以"Response"结尾，就像以前所用的"fooResponse"。每个＜part＞元素都有名字和类型属性，就像函数的参数有参数名和参数类型。<br /><br />　　用于交换文档时，WSDL允许使用＜message＞元素来描述交换的文档。<br /><br />　　＜part＞元素的类型可以是XSD基类型，也可以是SOAP定义类型(soapenc)、WSDL定义类型(wsdl)或是Types栏定义的类型。<br /><br />　　一个PortTypes栏中，可以有零个、单个或多个＜portType＞元素。由于抽象PortType定义可以放置在分开的文件中，在某个WSDL文件中没有＜portType＞元素是可能的。上面的例子里只是用了一个＜portType＞元素。而一个＜portType＞元素可在＜operation＞元素中定义一个或是多个操作。示例仅使用了一个名为"foo"的＜operation＞元素。这和某个函数名相同。＜operation＞元素可以有一个、两个、三个子元素：＜input＞, ＜output＞ 和＜fault＞元素。每个＜input＞和＜output＞元素中的消息都引用Message栏中的相关的＜message＞元素。这样，示例中的整个＜portType＞元素就和以下的C函数等效：<br /><br />　 
<table height="25" width="603" align="center" border="0"><tbody><tr bgcolor="#ebe9eb"><td>　int foo(int arg);</td></tr></tbody></table><br />　　这个例子足见XML和C相比要冗长的多。（包括＜message＞元素，XML在示例中共使用了12行代码来表达相同的单行函数声明。）<br /><br />　　Bindings栏可以有零个、一个或者多个＜binding＞元素。它的意图是制定每个＜operation＞通过网络调用和回应。Services栏同样可以有零个、一个、多个＜service＞元素。它还包含了＜port＞元素，每个＜port＞元素引用一个Bindings栏里的＜binding＞元素。Bindings和Services栏都包含WSDL文档。<br /><br />原文地址:http://www.yesky.com/20011013/200759_1.shtml<img src ="http://www.blogjava.net/esoa/aggbug/86901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-12-11 14:44 <a href="http://www.blogjava.net/esoa/articles/86901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：配置XFire </title><link>http://www.blogjava.net/esoa/articles/75808.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Wed, 18 Oct 2006 01:36:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/75808.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/75808.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/75808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/75808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/75808.html</trackback:ping><description><![CDATA[原文地址：<a href="http://javaresearch.org/article/showarticle.jsp?column=5&amp;thread=50134"><font color="#1a8bc8">http://javaresearch.org/article/showarticle.jsp?column=5&amp;thread=50134</font></a><br /><br /><br />在进行所有的开发之前，自然是到<a href="http://xfire.codehaus.org/"><font color="#1a8bc8">http://xfire.codehaus.org</font></a>下载最新的xfire的发布版本，在写这篇文档的时候，xfire最新的版本是xfire-distribution-1.1-beta-1版，从官方网站下载到本地机器后，解压，目录结构如下：<br /><br />xfire-distribution-1.1-beta-1<br /><br />|____api (javadoc文档)<br /><br />|____sample (几个xfire例子)<br /><br />|____lib (xfire所需的jars)<br /><br />|____modules (xfire 模块)<br /><br />|____xfire-all-1.1-beta-1.jar<br /><br />|____几个授权和说明TXT文档<br /><br /> <br /><br />它所提供的例子需要Maven2编译执行，如果你还没有安装Maven，可以到apache网站下载安装。在你阅读的这篇教程的例子中，我将采用ant进行编译，毕竟Ant才是大家所常用的项目管理编译工具。<br /><br /> <br /><br />在你的tomcat的webapps建立一个web应用程序，例如xfire，目录结构如下：<br /><br />       xfire<br /><br />         |____WEB_INF<br /><br />                |____web.xml<br /><br />             |____classes<br /><br />             |____lib<br /><br /> <br /><br />将下载解压的xfire-distribution-1.1-beta-1\lib文件夹下的所有的jar放入的这个lib文件夹下(tomcat/webapps/xfire/WEB-INF/lib)、将xfire-distribution-1.1-beta-1\xfire-all-1.1-beta-1.jar放入到tomcat/webapps/xfire/WEB-INF/lib文件夹下。<br /><br />将xfire-distribution-1.1-beta-1\examples\book\src\webapp\WEB-INF下的web.xml文件复制到tomcat/webapps/xfire/WEB-INF文件夹下。<br /><br />Web.xml的内容如下：<br /><div class="codeStyle"><ol><li><i><font color="#339900">&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;</font></i></li><li></li><li><i><font color="#339900">&lt;!-- START SNIPPET: webxml --&gt;</font></i></li><li></li><li><i><font color="#339900">&lt;!DOCTYPE web-app</font></i></li><li></li><li><i><font color="#339900">    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"</font></i></li><li></li><li><i><font color="#339900">    "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;</font></i></li><li></li><li><i><font color="#339900">   </font></i></li><li></li><li><i><font color="#339900">&lt;web-app&gt;</font></i></li><li></li><li><i><font color="#339900"></font></i></li><li></li><li><i><font color="#339900">  &lt;servlet&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;display-name&gt;XFire Servlet&lt;/display-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-class&gt;</font></i></li><li></li><li><i><font color="#339900">        org.codehaus.xfire.transport.http.XFireConfigurableServlet</font></i></li><li></li><li><i><font color="#339900">    &lt;/servlet-class&gt;</font></i></li><li></li><li><i><font color="#339900">  &lt;/servlet&gt;</font></i></li><li></li><li><i><font color="#339900"></font></i></li><li></li><li><i><font color="#339900">  &lt;servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;url-pattern&gt;/servlet/XFireServlet/*&lt;/url-pattern&gt;</font></i></li><li></li><li><i><font color="#339900">  &lt;/servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900"></font></i></li><li></li><li><i><font color="#339900">  &lt;servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;</font></i></li><li></li><li><i><font color="#339900">  &lt;/servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900">&lt;/web-app&gt;</font></i></li></ol></div><br />启动tomcat,然后打开浏览器，在浏览器地址栏中输入http://localhost:8080/xfire/services/，如何能够正常显示页面，说明xfire就配置成功了。<br /><br /> <br />这样，我们的XFire就配置完成了。<br /><img src ="http://www.blogjava.net/esoa/aggbug/75808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-10-18 09:36 <a href="http://www.blogjava.net/esoa/articles/75808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XFire：轻松简单地开发Web Services </title><link>http://www.blogjava.net/esoa/articles/75805.html</link><dc:creator>comchyi</dc:creator><author>comchyi</author><pubDate>Wed, 18 Oct 2006 01:28:00 GMT</pubDate><guid>http://www.blogjava.net/esoa/articles/75805.html</guid><wfw:comment>http://www.blogjava.net/esoa/comments/75805.html</wfw:comment><comments>http://www.blogjava.net/esoa/articles/75805.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/esoa/comments/commentRss/75805.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/esoa/services/trackbacks/75805.html</trackback:ping><description><![CDATA[
		<div class="postText">问一下.Net的开发者，开发Web Services有多困难?他们会被你的问题逗乐，他们会告诉你所有步骤花费的时间不会超过一分钟。再问一下Java开发者，运气好的话你会碰到上面的回答，一般情况下，你会得到一个完全不同的答案。从Web Services引入到Java中至今已经5年了，然而它仍然被认为是一门较新的技术，一个主要的原因就是使用Java实现Web Services太困难了。现在，随着新一代Web Services引擎XFire的发布，这种情况将会发生明显的变化。使用XFire，你可以把Java类方法发布为Web Services而不需要编写额外的代码。在这篇文章中，你将会看到XFire使Web Services开发变得多么容易和简单。 
<p>　　Web Services使我们能够在网络上建立分布式系统，应用程序组件可以通过任何平台、任何语言和任何方式访问。无论应用程序如何开发，使用了什么语言，以及运行在什么操作系统平台上，只要它作为Web Service，并且为协同解决问题而设计，那么你的应用程序，以任何语言开发或在任何平台上，都可以利用它的服务。这是Web Service的主要概念。</p><p>　　为了实现Web Services的平台无关性和实现访问独立性，软件行业需要遵循一些作为标准的技术。其中一些包括:</p><p>　　---XML:在Web Services环境中各层之间进行传递的默认数据格式。</p><p>　　---SOAP:封装和交换信息的默认协议。第一次被提出时，它是只取Simple Object Access Protocol(简单对象访问协议)的首字母。但是现在SOAP更多被认为是一个特定的名词，以它自己而命名，同样很多人认为这是用词不当:SOAP实际上不是用来访问对象的。另外，它也不再简单。</p><p>　　---WSDL(Web Services Description Language，Web Services描述语言):描述Web Services的语言。尽管基于XML并且可以被人理解，WSDL主要是由机器处理，由客户端程序读取和理解。</p><p>　　下面的高级层次图表，基于WWW协会发布的“Web Services Architecture”(Web Services架构)文档，显示了这些技术在实际的工作环境中是如何发挥作用:</p><p><a href="http://searchwebservices.techtarget.com.cn/TLimages/picview/?/imagelist/06/39/6fu472rkvoe2.jpg" target="_blank"><img style="BORDER-LEFT-COLOR: #000000; BORDER-BOTTOM-COLOR: #000000; BORDER-TOP-COLOR: #000000; BORDER-RIGHT-COLOR: #000000" alt="点击放大此图片" src="http://searchwebservices.techtarget.com.cn/imagelist/06/39/6fu472rkvoe2s.jpg" border="0" /></a></p><p>　　这个流程图显示了Web Services中的核心技术是如何工作的。</p><p>　　这里，Provider是提供服务的应用程序组件，Requester是使用服务的客户端程序。很多其他技术也会参与到交互中，但是这个图只显示了在Web Services环境中必需的核心技术组件。</p><p>　　XFire是一个免费的开源SOAP框架，它不仅可以极大方便地实现这样一个环境，并且可以提供许多Web Services规范中高级特征，这些特征在多数的商业或者开源工具都没有提供。你要恰当的理解这些单词:great ease and simplicity(非常轻松和简单)。你将会看到使用XFire创建Web Services是多么的简单。</p><p>　　假如你的Web应用有一个Java类，并且你想把它的一个方法发布为Web Services，当使用XFire时，你不需要编写一行额外的Java代码。只需要编辑发布描述符，然后你就会得到一个Web Services。是的，它相当地简单。我们来看一个例子。<strong>一个简单的Java类</strong></p><p>　　我们的例子是一个银行业应用程序，服务器是运行在J2SE1.4.2_07下的Apache Tomcat5.5.7。假定你已经了解如何使用Java编写Web应用程序，并知道应该如何把它部署到Apache Tomcat服务器上。我们的Web应用程序非常简单;它只做一件事——将资金从一个账户转到另外一个账户上。一个普通的Java类BankingService包含了一个叫做transferFunds()的方法来为我们完成这项工作。它需要四个输入参数:</p><ul><li>　　1、 String fromAccount 
</li><li>　　2、 String toAccount 
</li><li>　　3、 double amount 
</li><li>　　4、 String currency</li></ul><p>　　代码如下:</p><p></p><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3"><p><font face="Verdana">package com.mybank.xfire.example;</font></p><p><font face="Verdana">import java.text.NumberFormat;<br />import java.text.DecimalFormat;</font></p><p><font face="Verdana">/** XFire WebServices sample implementation class. <br />*/<br />public class BankingService implements IBankingService {<br />    <br />    //Default constructor.<br />    public BankingService(){    <br />    }<br />    <br />    /** Transfers fund from one account to another.<br />    */<br />    public String transferFunds(<br />        String fromAccount, String toAccount, double amount, String currency){<br />        <br />        String statusMessage = "";<br />                      <br />        //Call business objects and other components to get the job done.<br />        //Then create a status message and return.<br />        try {<br />            NumberFormat formatter = new DecimalFormat("###,###,###,###.00");       <br />            statusMessage = "COMPLETED: " + currency + " " + formatter.format(amount)+ <br />            " was successfully transferred from A/C# " + fromAccount + " to A/C# " + toAccount;<br />        } catch (Exception e){<br />            statusMessage = "BankingService.transferFunds(): EXCEPTION: " + e.toString();<br />        }<br />        return statusMessage;<br />    }<br />    <br />}</font></p></td></tr></tbody></table><p>　　在这里你看到了什么异常的东西了吗?或许没有，除了默认的构造函数，类型是public。这是必须的。否则，XFire不能够初始化这个类。因为使用接口的设计是一个好的实践，所以我们的Java类也实现了一个称为IBankingService的接口。代码十分简单:</p><p></p><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3"><p><font face="Verdana">package com.mybank.xfire.example;</font></p><p><font face="Verdana">public interface IBankingService {  </font></p><p><font face="Verdana">    public String transferFunds(<br />        String fromAccount, String toAccount, double amount, String currency);<br />        <br />}</font></p></td></tr></tbody></table><p>　　在实际实现中，这样一个方法可能包括各种类型的复杂调用、查询和处理操作。但是我们的示例代码已经最小化了，以至于我们可以集中精力在主要目标上:把这个方法发布为Web Services。</p><p>　　你可以看到BankingService是一个普通的Java类，没有任何代码告诉我们它将会在Web Services中使用。好的，这里我们不需要增加任何东西。我们所有的工作都在部署描述符里完成。</p><p>　　<strong>Web应用的部署描述符</strong></p><p>　　在Java中，Web应用程序通常需要至少一个部署描述符(叫做web.xml)对其进行配置。XFire本身是一个基于servlet的应用程序。因此，我们需要增加必要的引用到描述符文件中。然后我们还必须配置将要创建的Web Services。我们使用一个称为services.xml的新文件来完成这件事。</p><p>　　<strong>web.xml</strong></p><p>　　首先，修改web.xml。我们需要增加下面的XFire servlet相关的条目:</p><p></p><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3"><p><font face="Verdana">&lt;servlet&gt;<br />        &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;<br />        &lt;display-name&gt;XFire Servlet&lt;/display-name&gt;<br />        &lt;servlet-class&gt;org.codehaus.xfire.transport.http.XfireConfigurableServlet<br />         &lt;/servlet-class&gt;<br />    &lt;/servlet&gt;</font></p><p><font face="Verdana">    &lt;servlet-mapping&gt;<br />        &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;<br />        &lt;url-pattern&gt;/servlet/XFireServlet/*&lt;/url-pattern&gt;<br />    &lt;/servlet-mapping&gt;<br />    <br />    &lt;servlet-mapping&gt;<br />        &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;<br />        &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;<br />    &lt;/servlet-mapping&gt;</font></p></td></tr></tbody></table><strong><font face="Verdana">services.xml</font></strong><p>　　现在我们不得不说一下我们的Web Services的由什么组成的了。这由一个叫做services.xml的文件完成，它存放在META-INF/xfire目录下，而这整个目录放在WEB-INF/classes文件夹中，它在Web应用程序的标准类路径中。这里是services.xml中的基本配置条目:</p><p></p><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3"><font face="Verdana">&lt;beans xmlns="http://xfire.codehaus.org/config/1.0"&gt;<br />  <br />  &lt;service&gt;<br />    &lt;name&gt;Banking&lt;/name&gt;<br />    &lt;namespace&gt;mybank&lt;/namespace&gt;<br />    &lt;serviceClass&gt;com.mybank.xfire.example.IBankingService&lt;/serviceClass&gt;<br />    &lt;implementationClass&gt;com.mybank.xfire.example.BankingService&lt;/implementationClass&gt;<br />  &lt;/service&gt;  <br />  <br />&lt;/beans&gt;</font></td></tr></tbody></table><p> 　　让我们看看这里都包含了什么内容。Web Services的定义包含在<service>元素中，它还含有一些子元素。第一个子元素是<name>，它可以是你提供任何的合法名字。这将会被客户端程序和其它需要定位你的服务的组件用到。例如，在服务准备好以后，你将在浏览器上使用这个名字来查看WSDL。</name></service></p><p>　　<font face="Verdana">下一个子元素是&lt;namespace&gt;。任何合法的XML名字都是可以的。&lt;namespace&gt;用来唯一标识你的服务的各个参数。<br />&lt;serviceClass&gt;元素包含了Java类的名字，它指定了方法签名。在我们的例子中，它是接口IBankingService。如果Java类没有实现任何接口，你就需要把类的名字放在这里。在你的Java类或者接口中可能有几个方法。只需要一个入口把它们全部发布为Web Services。</font></p><p><font face="Verdana">　　&lt;implementationClass&gt;保存了实现方法的Java类名。这是一个可选元素。如果上一个元素&lt;serviceClass&gt;包含了一个接口，那么相应的实现类必须在这里指定。</font></p><p><font face="Verdana">　　就是这样。我们的Web Services配置完成了</font>。</p><p>　　<strong>XFire和其它类库</strong></p><p>　　现在是最后一步了，需要得到所有必需的类库。我们怎样得到它们呢?去XFire网站，下载xfire-distribution-1.0.zip，然后解压到一个本地文件夹。复制下面的jar文件和它的库文件夹到WEB-INF/lib中:</p><ul><li>　　• activation-1.0.2.jar 
</li><li>　　• commons-codec-1.3.jar 
</li><li>　　• commons-httpclient-3.0.jar 
</li><li>　　• commons-logging-1.0.4.jar 
</li><li>　　• jaxen-1.1-beta-8.jar 
</li><li>　　• jdom-1.0.jar 
</li><li>　　• log4j-1.2.x.jar 
</li><li>　　• mail-1.3.3_01.jar 
</li><li>　　• spring-1.2.x.jar 
</li><li>　　• stax-api-1.0.jar 
</li><li>　　• wsdl4j-1.5.2.jar 
</li><li>　　• wstx-asl-2.9.jar 
</li><li>　　• xbean-2.1.0.jar 
</li><li>　　• xbean-spring-2.2.jar 
</li><li>　　• xfire-all-1.0.jar 
</li><li>　　• XmlSchema-1.0.jar</li></ul><p>　　一切妥当。我们来部署和启动应用程序。为了部署示例应用，只需要复制websvc.war到Apache Tomcat的webapps文件夹中，再等待几秒钟。它将会自动启动。这个应用的全部源代码也包含在这个war文件中。我们的程序已经准备作为一个Web Service了。<strong>我们如何知道Web Service正在工作呢?</strong></p><p>　　为了了解Web Service是否正在工作，我们需要测试。首先，我们测试来看WSDL是否可用。我们在浏览器中输入URL。哪个URL?因为我们的应用程序的war文件是websvc.war，并且在services.xml中给出的服务名是Banking，WSDL的URL应该是:http://localhost:8080/websvc/services/Banking?wsdl。</p><p>　　请注意:URL的第一部分，例如，http://localhost:8080，可能会根据你的应用服务器不同而不同。无论怎样，当你输入URL后，将会看到一个XML文档，它的根元素是<?xml:namespace prefix = wsdl /?><wsdl:definitions>。这个文档叫做服务的WSDL。如果你看到了，这就是你的应用作为Web Service已经可用的第一个证明。</wsdl:definitions></p><p>　　但是这个测试是不够的。可能会发生这种情况，可以看到WSDL，但是从客户端程序可能会访问不到服务。因此为了核实服务是否可以访问了，我们必须使用一个客户端进行服务的实际调用来进行一个真正的测试。</p><p>　　<strong>开发一个客户端</strong></p><p>　　你可以使用任何的SOAP工具创建客户端，例如，.Net或者Apache Axis，有很多种方法:使用从WSDL产生的stubs，使用动态代理，等等。在例子中，我们使用一个动态代理，以一个简单的Servlet形式，叫做WsClient.java。为了保持代码两最小，所有在屏幕显示的元素都放在了doGet()方法中。对Web Service的实际调用由callWebService()方法完成，它相当地简单。和下面的类似:</p><p></p><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3"><p><font face="Verdana">/* Call the Web service<br />    *<br />    */<br />    public String callWebService(<br />        String fromAccount, String toAccount, double amount, String currency) <br />        throws MalformedURLException, Exception {<br />        <br />        //Create a metadata of the service      <br />        Service serviceModel = new ObjectServiceFactory().create(IBankingService.class);        <br />        log.debug("callSoapServiceLocal(): got service model." );<br />   <br />        //Create a proxy for the deployed service<br />        XFire xfire = XFireFactory.newInstance().getXFire();<br />        XFireProxyFactory factory = new XFireProxyFactory(xfire);      <br />    <br />        String serviceUrl = "http://localhost:8080/websvc/services/Banking";<br />        <br />        IBankingService client = null;<br />        try {<br />            client = (IBankingService) factory.create(serviceModel, serviceUrl);<br />        } catch (MalformedURLException e) {<br />            log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());<br />        }    <br />               <br />        //Invoke the service<br />        String serviceResponse = "";<br />        try { <br />            serviceResponse = client.transferFunds(fromAccount, toAccount, amount, currency);<br />       } catch (Exception e){<br />            log.error("WsClient.callWebService(): EXCEPTION: " + e.toString());                 <br />            serviceResponse = e.toString();<br />        }        <br />        log.debug("WsClient.callWebService(): status=" + serviceResponse);              </font></p><p><font face="Verdana">        //Return the response<br />        return serviceResponse;<br />    } </font></p></td></tr></tbody></table><p>　　这个代码是如何工作的呢?我来解释一下:首先，我们创建一个服务模型，它包含服务的说明——换句话说，就是服务的元数据。我们使用XFire的ObjectServiceFactory从IBankingService.class接口创建这个模型。</p><p>　　接着，为XFire获得一个代理工厂对象，它包含了常规的代码，也相当地简单和易懂。这一步中没有任何特定应用的东西。从这个proxyFactory，使用服务模型和服务端点URL(用来获得WSDL)，我们可以得到一个服务的本地代理。就是它了。这个代理就是实际的客户端。现在，我们可以调用它的transferFunds()方法来得到我们需要的Web Service。</p><p>　　一旦示例应用发布并启动，就可以尝试servlet URL:</p><p>　　http://localhost:8080/websvc/ws。</p><p>　　这个Servlet使用默认参数来调用Web Service和显示接收到的响应。页面的最后两行应该读取:</p><p>　　Response Received<br />　　COMPLETED: CDN$ 500.00 was successfully transferred from A/C# 11111-01234 to A/C# 99999-05678</p><p>　　现在你可以确定Web Service已经发布并且在运行中了。</p><p>　　为了尝试不同的输入值，你可以使用完整的URL，例如:</p><p>　　http://localhost:8080/websvc/ws?from=11-2345&amp;to=77-9876&amp;amt=250.00&amp;cur=EUR。</p><p>　　<strong>基本的Web Services开发步骤清单</strong></p><p>　　这个清单总结了将一个Java方法发布为Web Service所必须的步骤:</p><ul><li>　　1、 检查Java类的方法和默认构造函数确保为public 
</li><li>　　2、 增加XFire servlet相关条目到web.xml中 
</li><li>　　3、 创建services.xml，把它放到WEB-INF/classes/META-INF/xfire目录下 
</li><li>　　4、 增加XFire和第三方包到你的Web应用的WEB-INF/lib文件夹中</li></ul><p>　　这就是所有需要的步骤，是的，相当简单。</p><p>　　<strong>XFire的其他高级特性</strong></p><p>　　XFire的使用可能比较简单，但是在特性和功能性上，它却占据着领导者的位置。下面是它的高级特性:</p><ul><li>　　---本地数据绑定支持POJOs(plain-old Java objects)、XMLBeans、JAXB(Java Architecture for XML Binding)、Castor等等。数据绑定说明了Web Services的XML请求和映射到Java对象的XML响应。 
</li><li>　　---使用StAX(Streaming API for XML)处理XML文档。同DOM的基于树和SAX的事件驱动的处理方式相比，StAX使用了拉(pull)机制，它使处理更快速，内存效率更高。 
</li><li>　　---支持多种传输协议，如HTTP、JMS(Java Message Service)和JVM内部传输。 
</li><li>　　---嵌入式，这是XFire的核心功能之一。你可以把这个SOAP引擎嵌入到你的应用中，完全隐藏所有XFire特定引用，同样所有配置都是程序驱动。 
</li><li>　　---丰富的API，它使XFire可高度自定义，允许开发者在不同的阶段截获请求，并且对他们进行处理。 
</li><li>　　---兼容最新的标准例如SOAP1.1(没有加密远程工程调用，或者RPC)和1.2、WSDL1.1、the Web Services Interoperability Organization’s Basic Profile 1.0、Web Services Addressing和WS-Security。</li></ul><p>　　最重要的是，XFire属于新一代Web Services引擎。不仅仅是营销用语，“新一代”有一些重要的意义。Apache Axis是第一代Java语言的Web Services引擎，已经成为了所有后来工具的参考标准。在过去的几年里，Axis以及这些其它的工具已经在很多生产环境中进行了实地测试。从中得出的一个关键的问题就是Web Services并不最适合RPC类型的通信。对于性能和效率，面向文档的消息形式是最好的方式。但是Apache Axis和很多其他的Web Services引擎都被设计成了面向RPC的(尽管它们支持文档形式)。现在，整个行业正在开发新一代的SOAP引擎，设计为面向文档的。Apache已经宣布结束旧版本的Axis引擎开发，现在专注于Axis2，现在它的预发布版本是0.95。XFire在今年的2月份发布了它的第一个产品版本(1.0)。它的下一个版本(1.1)仅仅在几个星期之后就进行了发布。<strong>性能</strong></p><p>　　Web Services需要消耗很多资源，但是性能方面它们不是那么引人注目。XFire打破了这种趋势。它消耗更少的内存(部分因为 StAX的使用)，但是表现却比多数可比较的SOAP引擎出色。你可以在资源中提供的链接中看到比较的结果。</p><p>　　此外，XFire还提供了各种方法来进一步优化性能。一个方法是使用JVM内置传输(in-JVM transport)。如果你知道Web Services和客户端运行在同一个JVM上，你可以选择使用本地传输，它可以大幅提升性能。在示例中的客户端代码，看以下指定服务端点URL的这行:</p><p>　　String serviceUrl = "http://localhost:8080/websvc/services/Banking";</p><p>　　替换为</p><p>　　String serviceUrl = "xfire.local://Banking";</p><p>　　你会看到性能上的明显提高，因为它绕过了整个网络层。</p><p>　　<strong>局限性</strong></p><p>　　XFire有些重要的局限性你应该清楚:</p><ul><li>　　---开发Web Services的好的实践是从WSDL开始。大部分的SOAP引擎提供了从WSDL生成服务stub的工具。XFire也提供了这样一个工具。但是它是基于注释(annotations-based)的，因此需要J2SE5.0。对于仍坚持使用J2SE1.4.x的人来说，它不是一个令人拍手叫好的工具，因为我们有很多其他方式来编写客户端，一个就是文章中演示的方式。 
</li><li>　　---附件支持，它将会包含在未来发行的版本中。 
</li><li>　　---易于学习的用户向导。XFire团队在这个方面还有很多工作需要做。</li></ul><p>　　<strong>结论</strong></p><p>　　Java当前的趋势是简化技术的使用。因此，我们正看到一波基于POJO的开发成就。同时，面向服务架构(SOA，Services-oriented architecture)和Web Services已经变成了当前行业的热点话题。XFire正是在这种情况下产生的。它能够使POJO发布为最少的Web Services，而只需要付出最小化的努力。从而，它使希望使用这项技术的初级开发者的学习曲线变得平缓。同时，由于它兼容最新标准和提供了丰富的API，XFire为高级用户提供了更多的大好机会。</p><p><font face="Verdana">版权声明：Techtarget获Matrix授权发布,如需转载请联系Matrix<br />作者:Shahid Ahmed ;mydeman<br />原文:http://www.javaworld.com/javaworld/jw-05-2006/jw-0501-xfire.html<br />Matrix:http://www.matrix.org.cn/resource/article/2006-09-24/XFire_6bd1061c-4bc6-11db-978f-43b3336b7e51.html</font></p></div>
<img src ="http://www.blogjava.net/esoa/aggbug/75805.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/esoa/" target="_blank">comchyi</a> 2006-10-18 09:28 <a href="http://www.blogjava.net/esoa/articles/75805.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>