jdk6 WebService入門 .

另見文章:
 
1、            Web Services簡介
什麼是Web Services
Web service 就是一個應用程序,它向外界暴露出一個可以經過 Web進行調用的API。這就是說,你可以用編程的方法經過Web來調用這個應用程序。
基於瀏覽器的瘦客戶應用程序,即 BS結構,是目前流行的,使得Web Services的應用愈來愈普遍。Web Services 是一種構建應用程序的模型,並能在全部支持 Internet 通信的操做系統上實施運行。Web Services 令基於組件的開發和 Web 的結合達到最佳,基於組件的對象模型,利用 SOAP 和 XML對這些模型在通信方面做了進一步的擴展以消除特殊對象模型的障礙。由於是使用XML做爲傳輸的介質,因此能夠跨平臺跨語言。
Web Services 實現遠程訪問,有點相似 RMI(遠程方法調用)。 但它是利用 HTTP 和 SOAP 協議是商業數據在 Web 上傳輸,SOAP經過 HTTP 調用商業對象執行遠程功能調用,Web 用戶可以使用 SOAP 和 HTTP經過 Web 調用的方法來調用遠程對象。
Web Services 結構
客戶根據 WSDL描述文檔,會生成一個 SOAP 請求消息。Web Services 都是放在Web服務器上面,客戶生成的SOAP請求會被嵌入在一個HTTP POST請求中,發送到 Web 服務器來。Web 服務器再把這些請求轉發給 Web Services 請求處理器。請求處理器的做用在於,解析收到的 SOAP 請求,調用 Web Services,而後再生成相應的 SOAP 應答。Web 服務器獲得 SOAP 應答後,會再經過 HTTP應答的方式把信息送回到客戶端。
什麼是WSDL
WSDL是 Web Services Description Language的縮寫,是一個用來描述Web服務和說明如何與Web服務通訊的XML語言。Web Services服務器把一個對像綁定到一個URL 上(如http://localhost:8080/webservices/hello),客戶端就能夠能過綁定的地址(如:http://localhost:8080/webservices/hello?wsdl)取得WSDL文件,該文件是標準的XML 格式,描述了被綁定對像的信息,包括可調用的方法,參數,及參數類型,返回值類型,異常類型等。客戶端就是經過這些信息調用服務器的方法。
 
2、            JKD6 對Web Services的支持
JDK6提供了對Web Service原生的支持,對Web Service進行了完美的封裝,徹底隱藏了底層內容,甚至能夠不用瞭解wsdl的具體規範。使用Web Service就像使用本地方法同樣簡單。下面來舉個例子,依然從最簡單的HelloWorld入手。
HelloWorld例子
STEP 1 ,服務器端 Bean 說明
服務器端的Java類若要成爲一個實現了Web Service的bean,它須要遵循下邊這些原則:這個類必須是public類、不能是final的或者abstract、必須有一個公共的默認構造函數、絕對不能有finalize()方法。若要成爲一個實現了Web Service的Bean的方法必須遵循這些原則:
這個方法必須是public,它的參數、返回值、和異常在每一個JAX RPC規範中都描述了Java轉化成XML/WSDL映射文件的規則,參數和返回值能夠是原始類型、數組等等。
 
下面是服務器端的類HelloWorld.java:
package test.jws.service;
 
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
 
@WebService (targetNamespace = "http://www.jwstest.org" )
@SOAPBinding (style = SOAPBinding .Style. RPC )
public class HelloWorld {
    @WebMethod (action= "toSayHello" ,operationName= "toSayHello" ,exclude= false )
    @WebResult (name= "returnWord" ) // 自定義該方法返回值在 WSDL 中相關的描述
    public String sayHello( @WebParam (name= "userName" )String userName) {
        return "Hello:" + userName;
    }
    @WebMethod
    public int getExp( int i, int j) {
        return i / j;
    }
}
 
 
這是服務器端普通的業務類,經過@WebService、@WebMethod等註釋描述來生成WSDL文件。
 
STEP 2 ,執行 wsgen 命令
本例中到HelloWorld類所在的目錄中新建一個命名爲wsdl的文件夾,運行:wsgen -cp ./bin -r ./wsdl -s ./src -d ./bin -wsdl test.jws.service.HelloWorld。執行後會在wsdl文件夾中生成HelloWorld的wsdl描述文件,src文件夾中生成依賴類,如異常說明類,bin中生成依賴類的class文件
 
STEP 3 發佈 Web Service Bean
啓動服務類StartService.java:
package test.jws.service;
 
import javax.xml.ws.Endpoint;
 
public class StartService {
    public static void main(String[] args) {
        Endpoint.publish( "http://localhost:8080/webservice/hws" , new HelloWorld());
    }
}
 
 
此類很簡單,能過Endpoint類的publish()方法發佈實例發佈地址爲:
http://localhost:8080/webservice/hws,必需明確指明http協議,主機IP 地址及端口號,在IE上輸入 http://localhost:8080/webservice/hws?wsdl返回如下內容說明發布成功
<? xml version="1.0" encoding="UTF-8" ?>
< definitions xmlns =" http://schemas.xmlsoap.org/wsdl/ "
xmlns:tns =" http://www.jwstest.org "
xmlns:xsd =" http://www.w3.org/2001/XMLSchema "
xmlns:soap =" http://schemas.xmlsoap.org/wsdl/soap/ "
targetNamespace =" http://www.jwstest.org "
name =" HelloWorldService ">
< types />
< message name =" toSayHello ">
  <part name="userName" type="xsd:string" />
   </message>
 <message name="toSayHelloResponse">
  <part name="returnWord" type="xsd:string" />
   </message>
< message name =" getExp ">
  <part name="arg0" type="xsd:int" />
  <part name="arg1" type="xsd:int" />
   </message>
< message name =" getExpResponse ">
  <part name="return" type="xsd:int" />
   </message>
< portType name =" HelloWorld ">
< operation name =" toSayHello " parameterOrder =" userName ">
  <input message="tns:toSayHello" />
  <output message="tns:toSayHelloResponse" />
  </operation>
< operation name =" getExp " parameterOrder =" arg0 arg1 ">
  <input message="tns:getExp" />
  <output message="tns:getExpResponse" />
  </operation>
   </portType>
< binding name =" HelloWorldPortBinding " type =" tns:HelloWorld ">
  <soap:binding style="rpc"
transport =" http://schemas.xmlsoap.org/soap/http " />
< operation name =" toSayHello ">
  <soap:operation soapAction="toSayHello" />
< input >
  <soap:body use="literal"
namespace =" http://www.jwstest.org " />
  </input>
< output >
  <soap:body use="literal"
namespace =" http://www.jwstest.org " />
   </output>
   </operation>
< operation name =" getExp ">
  <soap:operation soapAction="" />
< input >
  <soap:body use="literal"
namespace =" http://www.jwstest.org " />
   </input>
< output >
  <soap:body use="literal"
namespace =" http://www.jwstest.org " />
   </output>
   </operation>
  </ binding >
< service name =" HelloWorldService ">
 <port name="HelloWorldPort"
binding =" tns:HelloWorldPortBinding ">
  <soap:address
location =" http://localhost:8080/webservice/hws " />
  </port>
  </service>
</ definitions >
 
STEP 4 生成客戶端執行類
在cmd命令中執行 wsimport  -d  ./bin  -s  ./src - p test.jws.client.ref
http://10.168.189.182:8080/webservice/hws?wsdl 後在在src目錄下生成客戶端調用的兩個類:
       test.jws.client.ref.HelloWorld.java 根據wsdl描述生成的客戶端執行類
test.jws.client.ref.HelloWorldServices.java 經過此類負責解悉wsdl初始化客戶端HelloWorld實例
在bin目錄下生成對應的類文件。
       注意:執行wsimport命令時 STEP 3的服務必需啓動,不然沒法生成
 
STEP 4 客戶端調用
客戶端調用過程ClientRun.java:
package test.jws.client;
 
import test.jws.client.ref.*;
 
public class ClientRun {
 
    /**
      * @param args
      */
    public static void main(String[] args) {
        HelloWorldService hws = new HelloWorldService();
        HelloWorld hw = hws.getHelloWorldPort();
        System. out .println(hw.getExp(9, 3));
        System. out .println(hw.toSayHello( "zhuoshiyao" ));
    }
 
}
 
啓動 STEP 3中的服務,運行ClientRun後,制控臺輸出:
3
Hello:zhuoshiyao
 
注意:經測試,用Endpoint.publish("http://localhost:8080/webservice/hws", new HelloWorld()) 方式在Tomcat6 中發佈,不會存在端口號與路徑衝突。
JKD6 中定義的Web Service註釋
 
1.        @WebService 標註要暴露爲Web Services的類或接口 ,用於申修飾類或接口,包含屬性
targetNamespace 定義命名空間,默認爲」http://」+」包名倒排」
name Web Service 的名稱,默認爲類名,例如:
< definitions targetNamespace =" http://service.jws.test/ "
name =" HelloWorldService ">
portName Web Service 的端口名稱
serviceName Web Service 的服務名稱,例如
                    <service name="HelloWorldService">
< port name =" HelloWorldPort "
binding =" tns:HelloWorldPortBinding ">
       ...
                    </port>
              </service>
2.        @SOAPBinding 定義Web Service 在SOAP中的消息協議,用於申修飾類或接口,包含屬性
style 定義消息的編碼類型
user 定義消息的格式化類型
3.        @WebMethod 定義Web Service運做的方法,包含屬性
action 操做的活動
operationName與此方法匹配的 wsdl:operation 的名稱
exclude 標註此方法是否被暴露,默認爲false
4.        @WebResult 定義返回值,返回值類型不能爲接口類或抽象類,並且必須有個不帶參的構造函數,包含屬性
name返回值的名稱
partName表示此返回值的 wsdl:part 的名稱
targetNamespace返回值的 XML 名稱空間
header若是爲 true,則結果是從消息頭而不是消息正文獲取的
5.        @WebParam 定義方法的參數,參數類型不能爲接口類或抽象類,並且必須有個不帶參的構造函數,包含屬性
name參數名稱
partName表示此參數的 wsdl:part 的名稱
targetNamespace參數的 XML 名稱空間
header若是爲 true,則結果是從消息頭而不是消息正文獲取的
mode參數的流向(IN、OUT 或 INOUT 之一)
 
wsgenwsimport命令說明
wsgen命令的主要功能是用來生成合適的JAX-WS。它讀取Web Service的終端類文件,在咱們的例子中就是test.jws.service.HelloWorld,同時生成全部用於發佈Web Service所依賴的源代碼文件和通過編譯過的二進制類文件,一般Web Service Bean中用到的異常類會另外生成一個描述Bean。它還能生成WSDL和符合規範的HelloWorld類Web Service。wsgen從資源文件生成一個完整的操做列表並驗證是合法的。若是Web Service Bean中的主法有申明拋出異常,這一步是必需的,不然服務器沒法綁定該對像。
命令參數說明:
-cp 定義classpath
-r 生成 bean的wsdl文件的存放目錄
-s 生成發佈Web Service的源代碼文件的存放目錄(若是方法有拋出異常,則會生成該異常的描述類源文件)
-d 生成發佈Web Service的編譯過的二進制類文件的存放目錄(該異常的描述類的class文件)
 
       wsimport命令的主要功能是根據wsdl文件生成客戶端存根及框架,負責與Web Service 服務器通訊,並在將其封裝成實例,客戶端能夠直接使用,就像使用本地實例同樣。
命令參數說明:
-d 生成客戶端執行類的class文件的存放目錄
-s 生成客戶端執行類的源文件的存放目錄
-p 定義生成類的包名
 
3、            附錄:WSDL說明
一、WSDL 文檔結構
WSDL 文檔是利用這些主要的元素來描述某個 web service 的:
元素
定義
<portType>
web service 執行的操做
<message>
web service 使用的消息
<types>
web service 使用的數據類型
<binding>
web service 使用的通訊協議
一個 WSDL 文檔的主要結構是相似這樣的:
<definitions>
<types>
   definition of types........
</types>
<message>
   definition of a message....
</message>
<portType>
   definition of a port.......
</portType>
<binding>
   definition of a binding....
</binding>
</definitions>
 
WSDL 文檔可包含其它的元素,好比 extension 元素,以及一個 service 元素,此元素可把若干個 web services 的定義組合在一個單一的 WSDL 文檔中。
WSDL 端口
<portType> 元素是最重要的 WSDL 元素。
它可描述一個 web service、可被執行的操做,以及相關的消息。
能夠把 <portType> 元素比做傳統編程語言中的一個函數庫(或一個模塊、或一個類)。
WSDL 消息
<message> 元素定義一個操做的數據元素。
每一個消息均由一個或多個部件組成。能夠把這些部件比做傳統編程語言中一個函數調用的參數。
WSDL types
<types> 元素定義 web service 使用的數據類型。
爲了最大程度的平臺中立性, WSDL 使用 XML Schema 語法來定義數據類型。
WSDL Bindings
<binding> 元素爲每一個端口定義消息格式和協議細節。
WSDL 實例
這是某個 WSDL 文檔的簡化的片斷:
<message name=" getTermRequest ">
   <part name=" term " type=" xs:string "/>
</message>
 
<message name=" getTermResponse ">
   <part name=" value " type=" xs:string "/>
</message>
 
<portType name=" glossaryTerms ">
 <operation name=" getTerm ">
        <input message=" getTermRequest "/>
        <output message=" getTermResponse "/>
 </operation>
</portType>
在這個例子中, <portType> 元素把 "glossaryTerms" 定義爲某個端口的名稱,把 "getTerm" 定義爲某個操做的名稱。
操做 "getTerm" 擁有一個名爲 "getTermRequest" 的輸入消息,以及一個名爲 "getTermResponse" 的輸出消息。
<message> 元素可定義每一個消息的部件,以及相關聯的數據類型。
對比傳統的編程, glossaryTerms 是一個函數庫,而 "getTerm" 是帶有輸入參數 "getTermRequest" 和返回參數 getTermResponse 的一個函數。
二、WSDL 端口
<portType> 元素是最重要的 WSDL 元素。
它可描述一個 web service、可被執行的操做,以及相關的消息。
端口定義了指向某個 web service 的鏈接點。能夠把它元素比做傳統編程語言中的一個函數庫(或一個模塊、或一個類),而把每一個操做比做傳統編程語言中的一個函數。
操做類型
請求 -響應是最普通的操做類型,不過 WSDL 定義了四種類型:
類型
定義
One-way
此操做可接受消息,但不會返回響應。
Request-response
此操走可接受一個請求並會返回一個響應
Solicit-response
此操做可發送一個請求,並會等待一個響應。
Notification
此造做可發送一條消息,但不會等待響應。
One-Way 操做
一個 one-way 操做的例子:
<message name=" newTermValues ">
   <part name=" term " type=" xs:string "/>
   <part name=" value " type=" xs:string "/>
</message>
 
<portType name=" glossaryTerms ">
   <operation name=" setTerm ">
      <input name=" newTerm " message=" newT
 
相關文章
相關標籤/搜索