歡迎您光臨本站 註冊首頁

Java SE 6 Web Service 之旅

←手機掃碼閱讀     火星人 @ 2014-03-10 , reply:0

在過去的幾個月里,Sun公司已經為Java平台的第6個版本(Java Platform Standard Edition 6)提供了二進位安裝文件,Java文檔和Java源代碼,就是知名的「野馬」.而且這飛馳的野馬要拉住你這車並不算晚.

一個顯而易見的問題是,「為什麼我應該關心?」對於這些質疑者,Java SE 6提升的性能包括擴平台性,從開放的程序管理到Java編譯器,到系統底層和屏幕組件,到在你的源代碼中混合腳本語言(支持JavaScript),到Swing的整潔的外觀,到XML數字簽名,到智能卡I/O API,到JMX監聽線程的升級,為Web服務的服務提供者使用Annotations註釋和更加簡單的客戶端管理——在我們要關心的時候,這些名字僅僅是這個平台中的一小部分新功能.(java.net站點提供了關於J2SE 6平台中所有的新功能.)

這篇文章中,我們僅僅關注Java SE 6中對於Web Services規範的升級以及JAX-WS(Java API for XML Web Services)2.0規範,這些升級是的我們Web Services的創建和調用變得更加容易.使用這些新功能,我們可以僅僅使用簡單的Annotations註釋從一個Java類創建Web Services;隨後,我們在調用這個服務的時候使用JAX-WS2.0.我們同樣可以給這個服務添加一個管理者用來截取這個服務調用而且將截取的SOAP消息傳輸到System.out從控制台列印出來.

事實上,這些功能曾在JSR181(Java Specification Request 181)和JSR224 (JAX-WS)規範中已經被認可了,只是Java的正式版本擁有這些功能使它更加主流;我們同樣期待Java IDE開發平台可以對這些功能進行良好的支持.

JavaEE5規範中,允許基於標準規範讓應用程序開發人員為Web Services提供服務端平台,JSR181和JSR224就是JavaEE5規範中的一部分.理論上講,若在不改變源代碼使用支持這些相同規範的應用程序伺服器,在Java SE 6環境中大規模地發布工程這些功能將會破壞早期的Web Services應用程序,這個最初是不希望的.

我們的「野馬」Web Service:服務端和客戶端
在我們穩定這匹野馬之前,我們先下載這篇文中重提及的zip文件,它主要包括下邊四個文件:
mustangws.zip包括了這篇文章中提及的Web Service服務端應用程序源代碼,構建文件和腳本文件.
mustangwsclient.zip包括了客戶端的源代碼,構建文件和腳本文件.
mustangws.jar包含了已經編譯過的服務端應用程序.
mustangwsclient.jar包含了已經編譯過的客戶端程序.

注意:你需要Java SE 6和Apache Ant這兩個軟體來運行這篇文章中的例子.

在你解壓之後,你將會看到兩個文件架,mustangws 和mustangwsclient,這兩個文件架內分別是Web Services的服務端和客戶端.兩個項目裡面都有同樣的src文件夾,裡面包含了Java的源文件和Apache Ant軟體需要的構建文件build.xml.這裡還有附加的wsgenMustang.bat 和wsimportMustang.bat兩個批處理文件,裡面包含了生成Web Services存根的控制台命令,我們將在下邊的章節中講到.Apache Ant的build.xml文件對於兩個應用程序而言都是放在mustangws 和mustangwsclient兩個根目錄中的.兩個文件中有同樣的ant任務init,compile,dist,clean和run.



我們Web Services的服務端根目錄裡面還有一個目錄wsdl,裡面放了通過wsgen生成的描述Web Service的WSDL(Web Services Description Language)文件.


Web Services Metadata

Web Services Metadata詳細說明了Annotations的使用,這個在JavaSE5中就被引入了.這些對你而言可能是新概念,Annotations就是能夠被源代碼使用的註釋;一般使用在類定義,函數,函數參數或者函數返回值中.這些Annotations實際上就是對編譯器,Java虛擬機和應用程序伺服器的一種指示或者暗示,告訴它們應該如何處理這些有註釋的代碼.Annotations語句使用一般是「@」開始後面跟著Annotation文本內容.比如,@Deprecated註釋用於在使用函數的過程中將函數定義時生成的警告去掉,這一點是的Annotations變成了第一個Java類中的構造.

當Web Services Metadata Annotations用於Java源代碼中的類定義和函數定義的時,配置Web Services將會相對簡單.Web Services Metadata規範將會跟著「以Java開始的」開發模式,這些意味著你定義一個Java類和函數,然後就對他們使用一個Web Services Metadata Annotation.對於Java開發者來說,比起通過WSDL文件創建Web Service來說通過Java類使用Annotation是創建Web Services更加自然的方法.這些Annotations註釋用來暗示Web Services的運行時引擎將Java類和它裡面的函數解釋成為Web Service和相應的Web Service操作.將這個引擎已經綁定在Java SE 6裡面了,但是Web Services Metadata仍然是Java EE 5裡面的一部分,你將看到眾多廠家還是提供了支持Annotation的應用程序伺服器.

我們的「野馬」Web服務端

我們不再啰嗦了,讓我們通過「野馬」Web Service的服務端的一部分來看看Web Services Metadata在實踐中的使用.瀏覽mustangws/src/com/techyatra/hellows目錄.你將會看到下邊的文件:

HelloServer 
Bootstrap
TraceHandler
HelloException
Person


打開HelloServer文件,裡面包含了Web Services Metadata Annotations定義,將一個簡單的Java類用作Web Service,下邊是一個實現了Service的bean文件:
package com.techyatra.hellows;

@WebService(name="HelloServer",targetNamespace=http://mustangws.techyatra.com/
, serviceName="HelloService")
@SOAPBinding(style=SOAPBinding.Style.RPC)
public class HelloServer
{
@WebMethod(operationName="hello", action="urn:hello")
public@WebResult(partName="result")String ping(@WebParam(partName="person",
mode=Mode.IN,targetNamespace="http://mustangws.techyatra.com/") Person person)
throws HelloException
{
if (person == null)
{
System.out.println("function: hello(null)... throwing exception");


throw new HelloException("0001", "Person is null");
}
else
{
System.out.println("function: hello(person.getTitle()
person.getName())");
return "Hello. " person.getTitle() person.getName() "!";
}
}
}


在上邊的代碼中,@WebService註釋是的類MustangServer實現了Web Service,而且@WebMethod標識類中ping方法作為WebService的操作,ping除開返回greeting的值就不會做其他的事情.

需要注意的是:不管你願意不願意,你都不能任意地將Annotation用於任何一個Java類和函數使其暴露為一個WebService和一個WebService操作.Java類若要成為一個實現了WebService的bean,它需要遵循下邊這些原則:
這個類必須是public類
這些類不能是final的或者abstract
這個類必須有一個公共的默認構造函數
這個類絕對不能有finalize()方法
若要成為一個實現了WebService的Bean這個Java類必須遵循這些原則:
這個類必須是public,它的參數、返回值、和異常在每個JAX RPC規範中都描述了Java轉化成XML/WSDL映射文件的規則等等.參數和返回值可以是原始類型、數組等等;異常都可以繼承Exception;請查閱Java API去看基於XML的遠程調用可以知道更多的信息.

現在我們已經擁有了合理規範,讓我們接近代碼來看看WebService Annotation的作用.注意:這篇文章不是描述所有Annotation 和所有的WebService Metadat規範裡面的所有成員.如果要了解細節自己去查閱JSR 181規範.

這裡有各種類型的Annotation.@WebService和@WebMethod是WSDL映射Annatotion.這些Annotation將描述Web Service的WSDL文檔元素和Java源代碼聯繫在一起.@SOAPBinding是一個綁定的annotation用來說明網路協議和格式.

@WebService annotation的元素name,serviceName和targetNamespace成員用來描述wsdl:portType,wsdl:service,和targetNameSpace生成WebService中的WSDL文件.

@SOAPBinding是一個用來描述SOAP格式和RPC的協議的綁定Annotation.

@WebMethod Annotation的operationName成員描述了wsdl:operation,而且它的操作描述了WSDL文檔中的SOAPAction頭部.這是客戶端必須要放入到SQAPHeader中的數值,SOAP 1.1中的一種約束.

@WebParam Annotation的partName成員描述了WSDL文檔中的wsdl:part.

@WebResult Annotation的partName成員描述了wsdl:part用來返回WSDL文檔的值.

HelloException類是一個含有屬性description和錯誤代碼的異常類,Person是一個只有lastname和firstname 屬性的簡單類.這些類都沒有被任何Annotation註釋過.

我們在HelloException中使用@WebFault確實很誘人,可是並非如此!Annotation是被wsgen用來生成異常bean.更加有趣的是,這個不是JSR 181規範中的一部分,但是是JAX-RPC 1.1中的一部分.



在我們轉移到wsgen之前,一個很好的功能需要我們注意的是我們如何重載一個函數是的它成為一個WebService的操作.我們通過不同的@WebMethod的operationName元素值來激活這個功能,這裡的重載函數hello()和hello(person)有了不同的operationName元素各自命名為hello和quickHello.

現在為我們的服務應用程序運行Apache Ant的編譯工作.利用wsgen通過這樣的方式來生成build文件夾用來包含編譯過的class文件和一個wsdl文件夾用來放置WSDL文檔.

wsgen

擁有Web Service Annotation的HelloServer 類無法成功發布它包含了額外的沒有被註釋為WebService的HelloException類或者沒有綁定Java XML,如果HelloServer的函數沒有拋出異常,我們就不能使用wsgen.儘管如此,在實際應用中,這種做法是不推崇的;因此使用wsgen的目的是為了創建一個能夠使用WebService的類.

wsgen是一個命令行功能用來生成合適的JAX-WS.它讀取WebService的終端類文件,在我們的例子中就是com.techyatra.hellows.HelloServer,同時生成所有用於WebService發布的源代碼文件和經過編譯過的二進位類文件.它還隨意生成WSDL和符合規範的HelloServer類WebService.wsgen從資源文件生成一個完整的操作列表是合法的.

為了方便,這篇文章的源代碼mustangws文件夾中包含了一個wsgenHello.bat批處理文件,裡面包含了我們的Server項目中所需要的wsgen命令行的操作.

運行mustangws中的mustangws/wsgenHello.bat文件產生HelloExceptionBean源文件和編譯過的class文件放入com.techyatra.hellows.jaxb文件夾中.這些類綁定了關於Java-XML的所有操作.

現在我們有了發布WebService的所有需要的條件,在我們發布這個服務之前,讓我們再看一看將運行過程加入到WebService的調用隊列.這個相當敏捷萬一所有的通用過程都是調用這些服務所需要的過程,如此執行過程對所有的操作者來說都是合法的.操作者允許應用程序介紹自定義和核心商業需求域之外的特殊處理.這個操作者同樣會執行安全檢查,據使用統計,編碼和解碼數據,提供給其它模塊開發者使用.

Handlers
從客戶端(服務消費者)發送到服務端(服務提供者)的SOAP消息通過Java SE6中的JAX-WS處理管道來完成.Java SE 6提供了一個位於javax.xml.ws.handler包內的名為Handler的操作者解釋器,能夠插入到執行管道用來執行自定義、特殊應用程序程序傳送綁定或者沒有綁定的消息.兩種Handler的類型都是合法的:logical和SOAP.SOAP操作者能夠操作所有完整的SOAP消息,包括SOAP頭部和SOAP的主體,而logical操作者僅僅能夠操作SOAP主體有負載的部分.



我們的伺服器包括了com.techyatra.hello.TraceHandler SOAP 操作者.它解釋了沒有綁定和經過綁定的SOAP消息,而且將內容輸出在System.out顯示出來:

/*
* TraceHandler.java
* @author shahga
*/
package com.techyatra.hellows;
...
public class TraceHandler implements SOAPHandler<SOAPMessageContext>
{
...
public boolean handleMessage(SOAPMessageContext messageContext)
{
trace(messageContext);
return true;
}

public boolean handleFault(SOAPMessageContext messageContext)
{
trace(messageContext);
return true;
}
...

private void trace(SOAPMessageContext messageContext)
{
Boolean outMessageIndicator = (Boolean)
messageContext.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);

if (outMessageIndicator.booleanValue())
{
System.out.println("nOutbound SOAP:");
}
else
{
System.out.println("nInbound SOAP:");
}

SOAPMessage message = messageContext.getMessage();
try
{
message.writeTo(System.out);
System.out.println("");
}
catch (Exception exp)
{
System.out.println("Exception in TraceHandler:trace(messageContext) : "
exp);
}
}
}



TraceHandler實現了javax.xml.ws.handler.SOAPHandler< c extends MessageContext> 介面.方法handleMessage()和handleFault()將未綁定和沒有綁定的SOAP消息傳輸到System.out管道.這個功能提供給SOAPMessageContext,這部分聚合了所有SOAP消息,它包含了各種消息屬性和SOAP消息本身.

現在我們有一個準備好了操作者的WebService,我們應該如何包裝和部署這樣的服務呢?這個服務打包成下邊我們要討論的一個jar文件,但是看起來更加興奮.

Boostrap

在JavaSE6種,你將會看到javax.xml.ws包裡面包含了終端類,這些專門用來在JVM中部署WebService.當然,聽起來很正確!不需要任何伺服器.正好利用終端類創建一個服務實例,就像下邊顯示的Bootstrap類一樣.終端是用於小的應用程序的,應用伺服器消耗是不合理的,這裡是僅僅用作發布目的.

package com.techyatra.hellows;
...
public class Bootstrap
{
...
public static void main (String [] args) throws Exception
{
HelloServer server = new HelloServer();

Endpoint endpoint = Endpoint.publish(http://localhost:9090/HelloServer,
server);

Binding binding = endpoint.getBinding();


List<Handler> handlerChain = new LinkedList<Handler>();
handlerChain.add(new com.techyatra.hellows.TraceHandler());
binding.setHandlerChain(handlerChain);
}
}


這個Bootstrap類是一個便利的類用來聚合HelloServer WebService中的各個塊.它發布這個伺服器到一個URL地址而且將TraceHandler這個追蹤操作者添加到這個WebService運行管道中.

服務應用jar文件

運行Apache Ant中的命令創建編譯過的JAR.這個dist任務創建一個MustangWS.jar文件用來標誌com.techyatra.hellows.Bootstrap 類作為一個類包含了main()的入口點.

現在執行Apache Ant的run命令.這個將調用Bootstrap中的main()方法用來將WebService發布到http://localhost:9090/HelloServer.在你的瀏覽器裡面輸入http://localhost:9090/HelloServer?WSDL用來顯示動態生成的WSDL文檔的內容.讓我們看看WebService Metadata Annotation在WSDL中如何來提供各種服務的.

「野馬」WebSerice客戶端
現在我們將HelloServer發布成為了一個WebService,讓我們看看如何來調用它.當然這裡有很多方法來完成這個工作,我們將使用JavaSE 6中的JAX-WS2.0中的功能來調用HelloServer這個WebService.

這個客戶端應用程序在mustangwsclient 文件夾中可以找到.除開我們熟悉的src目錄和build.xml文件以外,mustangwsclient目錄中還包含了wsimportHello.bat批處理文件,用來生成JAXB的綁定存根.客戶端通過存根能夠很方便地調用這個服務.Java SE 6利用wsimport功能綁定生成這個存根,wsimportHello.bat使用這些功能為HelloService生成存根.

wsimport

wsimport能夠檢查WSDL文件中的特別URL是否合法然後生成所有的class用來讓客戶端更加清晰和容易懂得.有些人想使用SAAJ,JAXB或者straight-up XML用來調用WebService,可是需要小心的是,基於的wsimport的存根提供了一個方便的層次來管理WebService.它用來生成合適的JAX-WS機制,標識這些類可以和比較規範的應用程序伺服器和JVM來工作.

當你運行mustangwsclient文件夾中的wsimportHello.bat批處理文件,它將為Mustang WebService客戶端項目生成構建文件夾然後能夠使用關鍵的參數運行wsimport,這些用來生成存根文件,並且將其放在他們的com/techyatra/helloclient/jax文件夾中.若要知道細節,就查閱網上的資源.

HelloServer是一個服務端的終端介面.
HelloService是一個服務
HelloException是WSDL文檔中wsdl:fault映射過來的異常類.Person類是從WSDL文件中的Person模式中生成的Java類的綁定映射文件.
這些存根將會被HelloService客戶端應用程序使用,這些應用位於com.techyatra.helloclient.JAXClient 和 com.techyatra.helloclient.Client.



客戶端應用程序主要的入口點就是com.techyatra.helloclient.Client類,它接受命令行的參數,有需要的話執行參數重載和檢查,創建一個Person對象,經過JAXClient來調用這個對象.
package com.techyatra.helloclient;
public class Client
{
public static void main(String[] args) throws Exception
{
...
if (args[0].equals("jax"))
{
com.techyatra.helloclient.jax.Person person =
new com.techyatra.helloclient.jax.Person();
person.setTitle(args[1]);
person.setName(args[2]);
JAXClient jaxClient = new JAXClient();
jaxClient.invoke(person);
}
}
}


package com.techyatra.helloclient;
import com.techyatra.helloclient.jax.*;
public class JAXClient
{
...
public void invoke(Person person) throws Exception
{

HelloService service = new HelloService();
HelloServer server = (HelloServer) service.getHelloServerPort();
String ret = server.hello(person);
System.out.println(ret);
}
}


現在,執行Ant run命令將顯示下面的信息:
[java] No arguments specified. Overriding arguments to – jax Mr. Doe
[java] Alive and well. Thank you and hello Mr. Doe!

但是這正是我們想要的!
儘管我們沒有在這篇文章中討論到,但是基於Axis客戶端框架的代碼和WSDL2Java腳本文件都可以下載到,基於Axis框架的客戶段源代碼在mustangwsclient/com/techyatra/hellowsclient/AxisClient.java,而且包含了命令行參數的批處理文件wsdl2javaHello.bat,能夠在mustangwsclient根目錄中找到.若要刪除Axis引用,直接刪除mustangwsclient/com/techyatra/helloclient/axis目錄和mustangwsclient/com/techyatra/helloclient/AxisClient.java 源文件.

讓我們回顧一下我們這裡的WebService進行部署:
解開源代碼包.
針對我們的伺服器應用程序:
執行Ant編譯任務.
執行wsgenMustang.bat批處理文件生成所需要的文件.
執行Ant run任務調用來構建MustangWS.jar文件.
我們現在可以在http://localhost:9090/HelloServer中運行HelloServer服務,而且鍵入http://localhost:9090/HelloServer?WSDL還能夠看到動態生成的WSDL文檔內容.
針對客戶端應用程序:
如果對Axis沒有興趣就刪除mustangwsclient/com/techyatra/helloclient/axis目錄和mustangwsclient/com/techyatra/helloclient/AxisClient.java 源文件.
運行wsImportHello.bat批處理文件生成客戶端存根.
運行Ant的run任務就可以了.

資源:
Matrix Java&開源社區:http://www.matrix.org.cn


[火星人 ] Java SE 6 Web Service 之旅已經有645次圍觀

http://coctec.com/docs/java/show-post-61873.html