JAVA技巧:Java6中實現Web服務

字號:

在第二章中,我們演示了如何使用基本的POX-over-HTTP方法來實現Web服務,同時,我們也介紹了SOAP。SOAP現在已經成為業(yè)界不可或缺的技術和標準,因為當今大多數跨越合作伙伴的B2B的消息傳輸都是基于SOAP協議的。但SOAP(簡單對象訪問協議)是否象它的名字喻示的那樣“簡單”,人們仍有爭議。但有一點是毋庸置疑的,SOAP是一種開放的標準,業(yè)界提供了支持SOAP開發(fā)的工具和框架,對SOAP進行了廣泛的支持。幾乎所有的Web服務堆棧都采用了SOAP作為網絡傳輸協議,基于Java的Web服務框架更是如此。為了使用Java實現您自己的Web服務,或者在Java代碼中訪問第三方提供的Web服務,您需要了解,您有多種方法來實現Web服務。本章就來向您介紹在Java/J2EE環(huán)境下,實現Web服務的主要方法,它們分別是:
    (1) 使用JAX-WS 2.0來實現Web服務
    (2) 使用Apache Axis來實現Web服務
    (3) 使用Spring來實現Web服務
    (4) 使用XFire來實現Web服務
    我們將通過代碼實例,從頭開始演示如何使用上面的四種技術框架來創(chuàng)建Web服務,以及如何在代碼中訪問已有的Web服務。
    使用JAX-WS 2.0來實現Web服務
    JAX-WS是Java API for XML Web Service(XML Web服務的Java編程接口)的縮寫,JAX-WS2.0規(guī)范替代了以前的JAX-RPC1.0規(guī)范,它是基于JSR224規(guī)范的下一代Web服務開發(fā)的編程接口。
    JAX-WS2.0基礎
    JAX-WS2.0項目是在JAX-WS規(guī)范參考實現的代碼基的基礎上進行開發(fā)和演變的,您可以通過https://jax-ws.dev.java.net/ 了解這個項目?,F在,該項目既支持JAX-WS2.0規(guī)范,也支持JAX-WS2.1規(guī)范。
    下面列出了JAX-WS2.0實現中的一些新特性:
    (1) 直接支持基于JAXB2.0的數據綁定
    (2) 支持最新的W3C和WS-I標準(如SOAP 1.2、WSDL 1.2和SAAJ 1.3等標準)
    (3) 對Java和WSDL之間映射的元素據進行了標準化
    (4) 易于開發(fā)
    (5) 使Web服務的升級變得簡單
    (6) 對Web服務的處理器框架進行了升級
    (7) 支持異步RPC和非HTTP傳輸
    JAX-WS2.0另一個令人振奮的特點是,它已經包含在Java6標準版內,這意味著基于JAX-WS2.0的代碼和組件能在任何與J2EE兼容的服務器(如GlassFish服務器)上運行,同時,也可以在Java6標準版的環(huán)境下運行,這對Java開發(fā)者來說確實是一個很大的優(yōu)勢。而此前只有.Net的開發(fā)者享有這項權利(.Net棧支持輕量級的Web服務開發(fā))。
    在Java6平臺下,JAX-WS2.0提供了以下全新的API,用于創(chuàng)建Web應用和Web服務。
    API
    API所在的包
    JAX-WS
    javax.xml.ws
    SAAJ
    javax.xml.soap
    WS Metadata
    javax.jws
    在Java6標準版中實現Web服務
    下面我們先從最簡單的Web服務入手,不使用任何應用服務器和第三方Web服務器,而只是用Java6標準版及其自帶的工具,來開發(fā)并部署一個簡單的Web服務。
    服務器及客戶端代碼
    如前所述,我們現在就開始開發(fā)這個簡單的Web服務,這是我們的第一個示例,具體代碼請參見“ch03\01_JaxWS\JavaStandAlone”目錄。(譯者注:本書代碼請從http://www.packtpub.com/files/code/3216_Code.zip處下載。)
    服務器端代碼由三個Java文件構成,位于\ch03\01_JaxWS\JavaStandAlone\Server\src目錄,下面是對代碼的詳細解釋:
    Hello.java
    Hello是一個Java接口,其源代碼如下:
    public interface IHello{
    String sayHello (String name);
    }
    HelloImpl.java
    HelloImpl 實現了IHello接口中定義的業(yè)務邏輯方法,該方法將暴露出來作為Web服務。
    import javax.jws.WebService;
    import javax.jws.soap.SOAPBinding;
    import javax.jws.WebMethod;
    @WebService(name="IHello", serviceName="HelloService")
    @SOAPBinding(style=SOAPBinding.Style.RPC)
    public class HelloImpl implements IHello{
    @WebMethod(operationName = "sayHello")
    public String sayHello(String name){
    System.out.println("HelloImpl.sayHello...");
    return "\nHello From Server !! : " + name;
    }
    }
    在上面的HelloImpl的實現代碼中,我們可以看到一個叫javax.jws.WebService的Java注解,這個@WebService注解是將一個普通類定義為Web服務發(fā)布對象(亦稱終端,endpoint),javax.jws.soap.SOAPBinding這個注解指明了如何將Web服務綁定到SOAP消息上。HelloImpl只聲明了一個方法sayHello,該方法帶@WebMethod的注解,這個注解將會把該方法暴露給客戶端。其實,考試,大提示要創(chuàng)建一個JAX-WS服務并不需要IHello接口,我們這里只是讓大家保持良好的編程習慣而已?!elloServer.java
    HelloServer是服務器端的主類,它利用javax.xml.ws.Endpoint來發(fā)布Web服務,其代碼如下:
    import javax.xml.ws.Endpoint;
    public class HelloServer {
    public static void main(String args[]) {
    log("HelloServer.main : Creating HelloImpl...");
    IHello iHello = new HelloImpl();
    try{
    // Create and publish the endpoint at the given address
    log("HelloServer.main : Publishing HelloImpl...");
    Endpoint endpoint1 =
    Endpoint.publish("http://localhost:8080/Hello", iHello);
    log("HelloServer.main : Published Implementor...");
    }
    catch (Exception e) {
    System.err.println("ERROR: " + e);
    e.printStackTrace(System.out);
    }
    System.out.println("HelloServer Exiting ...");
    }
    }
    HelloClient.java
    Web服務客戶端代碼只有一個Java源文件,位于ch03\01_JaxWS\JavaStandAlone\Client\src目錄。HelloClient依賴于HelloService和IHello這兩個類,在我們后面對客戶端代碼進行編譯時,這兩個類可以自動生成??蛻舳说脑创a非常簡單明了:
    public class HelloClient {
    public static void main(String args[]) {
    log("HelloClient.main : Creating HelloImpl...");
    HelloService helloService = null;
    IHello helloImpl = null;
    String gotFromServer = null;
    try {
    log("HelloClient.main : Creating HelloImplService...");
    if (args.length != 0) {
    helloService = new HelloService(new URL(args[0]), new QName(
    args[1], args[2]));
    } else {
    helloService = new HelloService();
    }
    log("HelloClient.main : Retreiving HelloImpl...");
    helloImpl = helloService.getIHelloPort();
    log("HelloClient.main : Invoking helloImpl.sayHello(\"Binil\")...");
    gotFromServer = helloImpl.sayHello("Binil");
    log("HelloClient.main : gotFromServer : " + gotFromServer);
    } catch (Exception e) {
    System.err.println("ERROR: " + e);
    e.printStackTrace(System.out);
    }
    }
    }
    首先,您得實例化HelloServer接口,該實例中含有連接到Web服務所必須的管道;然后,您將會得到Web服務的端口引用,這樣,您就可以通過端口引用調用遠程的Web服務。
    運行服務器和客戶端
    如果您沒有修改過本章下載代碼中的examples.PROPERTIES文件,請先修改這個文件,將其中的路徑指向您的開發(fā)環(huán)境。另外,在本章的下載的代碼中,您也會看到一個README文件,這個文件給出了如何編譯和運行示例程序的具體說明。
    為了編譯并啟動服務器,您只需鍵入一個命令,請在命令行中切換到ch03\01_JaxWS\JavaStandAlone目錄,并執(zhí)行下面的命令:
    cd ch03\01_JaxWS\JavaStandAlone
    ant server
    一旦服務器起來并運行,您就可以在另一個命令行窗口中執(zhí)行ant client命令。當我們編譯客戶端代碼時,我們還需要使用下面的ant任務,從發(fā)布的Web服務中生成幾個客戶端類:
    
    
     line="-keep
    -d build
    -p com.binildas.ws.javastandalone.simple
    -s ${gensrc} http://localhost:8080/Hello?WSDL" />
    

    

    客戶端代碼將依賴于上面這幾個自動生成的類文件。運行完GenSrc任務后,我們就可以開始編譯客戶端代碼,并向服務器發(fā)送Web請求,并把從服務器接收到的應答打印在控制臺上,下面的命令將同時編譯和運行客戶端:
    cd ch03\01_JaxWS\JavaStandAlone
    ant client