用JAX-RPC開發(fā)Web服務(wù): Servlet作為Web服務(wù)端點(diǎn)
閱讀本文前您需要以下的知識(shí)和工具:
- JavaTM Web Services Developer Pack 1.1,并且會(huì)使用初步使用;
- 遼倩崾褂靡恢諩JB容器來(lái)開發(fā)、部署EJB,并且了解怎么在客戶端訪問(wèn)EJB組件;
- 對(duì)Apache axis Web服務(wù)開發(fā)工具有基本的了解;
- 基本的Java編程知識(shí)。
如果使用JAX-RPC開發(fā)Web服務(wù),我們幾種選擇:
- Servlet作為Web服務(wù)端點(diǎn);
- 無(wú)狀態(tài)會(huì)話Bean作為Web服務(wù)端點(diǎn);
- 基于消息(如JMS)的應(yīng)用程序作為Web服務(wù)端點(diǎn)。
本文以Servlet作為Web服務(wù)端點(diǎn)的情況來(lái)介紹JAX-RPC Web服務(wù)開發(fā),關(guān)于本篇文章中案例的介紹詳見(jiàn)本系列文章第一篇: 《用JAXM開發(fā)Web服務(wù)》。
本文的參考資料見(jiàn) 參考資料
本文的全部代碼在這里 下載
JAX-RPC,Java? API for XMLbased RPC,顧名思義,它是一種遠(yuǎn)程方法調(diào)用(或者說(shuō)遠(yuǎn)程過(guò)程調(diào)用),那么它和其它的遠(yuǎn)程方法調(diào)用(RPC, COM,CORBA,RMI)有什么區(qū)別呢?我們看一般的遠(yuǎn)程方法調(diào)用的結(jié)構(gòu),如圖1所示。
綜合比較常用的遠(yuǎn)程方法調(diào)用技術(shù),它們有以下的共性:
- 在客戶端和服務(wù)端有通用編程接口;
- 在客戶端有Stub,在服務(wù)端有Tie(有的叫Skeleton);
- 客戶端和服務(wù)端有專門的協(xié)議進(jìn)行數(shù)據(jù)傳輸。
對(duì)于通用接口的描述,比如CORBA有IDL of CORBA,Java RMI有Java RMI interface in RMI,對(duì)于XMLbased RPC來(lái)說(shuō),IDL就是WSDL(Web服務(wù)描述語(yǔ)言)。那么XMLbased RPC來(lái)說(shuō),什么是這個(gè)結(jié)構(gòu)中的"傳輸協(xié)議",當(dāng)然是SOAP,SOAP消息通過(guò)以傳輸文本為基礎(chǔ)的協(xié)議(HTTP、SMTP、FTP)為載體來(lái)使用的,也就是說(shuō),SOAP消息的傳輸建立在HTTP、SMTP、FTP傳輸協(xié)議之上。
JAX-RPC的構(gòu)架如下。
從上圖可以看出,客戶端調(diào)用的是JAX-RPC服務(wù)端點(diǎn)(Service Endpoint),這個(gè)服務(wù)端點(diǎn)是通過(guò)WSDL語(yǔ)言描述的。在這個(gè)體系結(jié)構(gòu)中,對(duì)于客戶端,可以是JS2E、J2ME或者J2EE平臺(tái)運(yùn)行環(huán)境;對(duì)于服務(wù)端,可以是J2EE1.3或者J2EE1.4容器(Servlet容器或者EJB容器)。Apache axis是一個(gè)很好的JAX-RPC運(yùn)行環(huán)境實(shí)現(xiàn),同時(shí)也提供了優(yōu)秀的開發(fā)工具,本文將使用它進(jìn)行開發(fā)。
使用Servlet作為服務(wù)端點(diǎn),本案例的基本構(gòu)架如下圖所示。
客戶端通過(guò)SOAP消息和JAX-RPC服務(wù)端交互,JAX-RPC服務(wù)端運(yùn)行在Servlet容器中,它通過(guò)調(diào)用EJB容器中的EJB組件來(lái)處理具體的業(yè)務(wù)邏輯。
使用JAX-RPC開發(fā)Web服務(wù),可以按照以下的步驟進(jìn)行:
- 服務(wù)端點(diǎn)定義;
- 服務(wù)描述;
- 服務(wù)端點(diǎn)實(shí)現(xiàn);
- 服務(wù)端點(diǎn)部署;
- 服務(wù)發(fā)布和發(fā)現(xiàn)。
注意:對(duì)于服務(wù)的發(fā)布和發(fā)現(xiàn),由于機(jī)制比較復(fù)雜,本文不討論,可能會(huì)在本系列文章進(jìn)行專題討論。
一個(gè)完整的JAX-RPC開發(fā)實(shí)例,將按照上面的5個(gè)步驟進(jìn)行,但是我們也可以使用非常簡(jiǎn)單的方式來(lái)發(fā)布一個(gè)Web服務(wù)。在介紹我們的案例前,讓我們用一分鐘快速開發(fā)一個(gè)Web服務(wù)。
首先安裝好JWSDP,你可以從 http://java.sun.com/webservices下載。
把本案例源代碼中的\src\bookservice.ear\web.war目錄拷貝到%JWSDP_HOME%\webapps目錄下,web.war文件里已經(jīng)包括了Apache axis運(yùn)行環(huán)境。
在%JWSDP_HOME%\classes目錄下新建一個(gè)HelloWorld.java文件,它的代碼如下:
例程1 最簡(jiǎn)單的Web服務(wù)HelloWorld
|
編譯這個(gè)類,然后編輯%JWSDP_HOME%\webapps\WEB-INF\server-config.wsdd文件,找到記,在其后面加入以下內(nèi)容:
|
在瀏覽器例輸入:
http://localhost:8080/web/services/HelloWorld?wsdl如果出現(xiàn)部署WSDL描述文件,那么最簡(jiǎn)單的Web服務(wù)已經(jīng)部署成功!
下面我們使用最簡(jiǎn)單的方式來(lái)調(diào)用這個(gè)Web服務(wù),在瀏覽器里輸入:
http://localhost:8080/web/services/HelloWorld?wsdl&method=sayHello&name=hellking那么在瀏覽器將會(huì)顯示以下內(nèi)容:
例程2 在瀏覽器里調(diào)用Web服務(wù)
|
如果結(jié)果是這樣,那么最簡(jiǎn)單的Web服務(wù)已經(jīng)部署成功,并且測(cè)試也通過(guò)了。注意"Hello!hellking"是調(diào)用Web服務(wù)返回的結(jié)果,它是我們期望的。下面我們來(lái)看一個(gè)完整的Web服務(wù)開發(fā)的例子。
服務(wù)端點(diǎn)定義的工作主要是確定"服務(wù)定義接口"(Service Definition Interface),有時(shí)也叫Web服務(wù)端點(diǎn)接口(Web services endpoint interface)。服務(wù)端點(diǎn)定義有兩中方法獲得:
- 使用某些工具從WSDL文件獲得;
- 直接使用Java語(yǔ)言編寫。
Apache axis提供了從WSDL文件中獲得Web服務(wù)端點(diǎn)的工具。您可以這樣使用:
|
使用這個(gè)命令前先設(shè)置好以下的環(huán)境變量,后面的介紹中還會(huì)使用axis工具,它們也要這樣設(shè)置環(huán)境變量:
|
關(guān)于WSDL2Java的更詳細(xì)的使用,請(qǐng)參考Apache axis的User Guides( http://ws.apache.org/axis/)。
我們這里直接使用Java編寫服務(wù)端點(diǎn)接口的方法。在本案例中,定義了三個(gè)業(yè)務(wù)方法,它們分別是查找所有的圖書、按書名查找圖書、按類別查找圖書。那么安照這三個(gè)業(yè)務(wù)方法,可以定義出以下的服務(wù)端點(diǎn)接口:
例程3 服務(wù)端點(diǎn)定義(BookServiceInterface.java)
|
上面代碼中的BookVO是一個(gè)序列化的對(duì)象,它有以下屬性,每個(gè)屬性都提供了getter和setter方法。
例程4 BookVO的部分代碼
|
編譯好這兩個(gè)類。
可以使用Java2WSDL從以上定義的服務(wù)端點(diǎn)接口中獲得服務(wù)描述(WSDL文件)。使用Apache axis工具,只要使用以下命令即可:
|
以上命令的解釋:
-o:生成的WSDL文件; -l:Web服務(wù)的位置; -n:這個(gè)WSDL文件的名字空間; -p:包到名字空間的映射;
最后一個(gè)參數(shù)是Web服務(wù)端點(diǎn)接口。
使用以上命令后,將生成一個(gè)名為temp.wsdl Web服務(wù)描述文。
有了服務(wù)描述文件,就可以使用它來(lái)生成JAX-RPC 的框架,這個(gè)框架使得我們編程變得簡(jiǎn)單,當(dāng)然您也可以直接編寫實(shí)現(xiàn)代碼,然后部署,但是那樣編程會(huì)變得困難。
使用以下的命令就可以生成這個(gè)框架:
|
使用這個(gè)命令后將生成以下文件:
BookServiceInterface.java:新的BookServiceInterface接口,它擴(kuò)展了java.rmi.Remote接口;
BookServiceInterfaceService.java:客戶端服務(wù)接口,用來(lái)獲得BookServiceInterface對(duì)象的引用;
BookServiceInterfaceServiceLocator.java:在客戶端使用,主要用來(lái)服務(wù)定位;
BookServletServiceSoapBindingImpl.java:服務(wù)端實(shí)現(xiàn)類,它實(shí)現(xiàn)了BookServiceInterface接口,服務(wù)端的業(yè)務(wù)方法實(shí)現(xiàn)代碼就在這里編寫;
BookServletServiceSoapBindingSkeleton.java:服務(wù)端Skeleton;
BookServletServiceSoapBindingStub.java:客戶端Stub;
BookVO.java:新的BookVO序列化對(duì)象;
deploy.wsdd:部署這個(gè)Web服務(wù)的腳本;
undeploy.wsdd:卸載這個(gè)Web服務(wù)的腳本。
服務(wù)端點(diǎn)實(shí)現(xiàn)類的基本框架已經(jīng)生成出來(lái)了,我們的任務(wù)就是往里面增加具體的業(yè)務(wù)內(nèi)容。下面我們來(lái)看具體的服務(wù)端點(diǎn)的實(shí)現(xiàn)。如例程3所示。
例程5 服務(wù)端點(diǎn)實(shí)現(xiàn)類
|
可以看出,服務(wù)端點(diǎn)的主要任務(wù)是調(diào)用EJB組件來(lái)完成業(yè)務(wù)邏輯的。
需要向讀者說(shuō)明的是,為了和本系列第一篇文章中的客戶端框架兼容(客戶端使用的值對(duì)象是com.hellking.webservice.BookVO,而這里由WSDL2Java生成的值對(duì)象是com.hellking.webservice.servlet.BookVO)。我們需要做以下的改動(dòng):
把生成的這些代碼中的com.hellking.webservice.servlet.BookVO全部改為com.hellking.webservice.BookVO,然后在Apache axis服務(wù)配置文件中申明這個(gè)BeanMapping,具體的聲明方法在后面介紹。
接下來(lái)的工作是編譯服務(wù)端相關(guān)的文件:BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton、BookServiceInterfaceService、BookServiceInterface。
啟動(dòng)服務(wù)器,這個(gè)服務(wù)器可以是任何能夠運(yùn)行Apache引擎Web服務(wù)器,當(dāng)然最好是同時(shí)有EJB容器和EJB容器的服務(wù)器,如Webphere 、Weblogic、JBOSS,如果沒(méi)有EJB容器,還需要一個(gè)額外的EJB容器,并且需要更改BookServletServiceSoapBindingImpl中獲得上下文(InitialContext)的方法,如:
例程6 獲得上下文環(huán)境
|
在控制臺(tái)中,轉(zhuǎn)到deploy.wsdd目錄下,執(zhí)行以下的命令就可以完成部署:
|
由于我們使用的是自己的序列化Bean對(duì)象,故要在%Web-Apps%/WEB-INF/ server-config.wsdd文件中做以下更改:
找到
|
在中間加入以下內(nèi)容:
|
部署后您必須確保在%Web-Apps%/WEB-INF/classes目錄下有服務(wù)端相關(guān)的類(BookServletServiceSoapBindingImpl、BookServletServiceSoapBindingSkeleton等)。
在瀏覽器里輸入(這個(gè)地址您需要根據(jù)具體情況更改):
http://localhost:8080/axis/services/BookServletService?wsdl
來(lái)驗(yàn)證Web服務(wù)是否已經(jīng)部署成功,如果部署不成功,您可以先嘗試重新啟動(dòng)服務(wù)器。
如果服務(wù)端已經(jīng)成功部署,下一步的工作就是編寫客戶端程序了。由于使用WSDL2Java已經(jīng)生成了客戶端的框架,所以我們的任務(wù)將相對(duì)簡(jiǎn)單了。
客戶端編程任務(wù)主要有以下幾個(gè):
- 在BookServletServiceSoapBindingStub里注冊(cè)BeanMapping;
- 編寫客戶端業(yè)務(wù)代表,這里使用了JAXRPCDelegate;
- 更改以前的BookGUI的部分程序。
在BookServletServiceSoapBindingStub里注冊(cè)BeanMapping
由于在SOAP消息中使用了序列化的BookVO對(duì)象,故在BookServletServiceSoapBindingStub中要進(jìn)行BeanMapping注冊(cè)。具體方法:
找到BookServletServiceSoapBindingStub中的getAllBooks,getTheBookDetail,getBookByCategory方法,在每個(gè)方法中的
|
前加入以下代碼:
例程7 在BookServletServiceSoapBindingStub注冊(cè)BeanMapping
|
注意這里的Qname要和server-config.wsdd中描述的名稱空間一致。在中server-config.wsdd,我們使用了以下的映射:
|
在編寫業(yè)務(wù)代表程序前,我們先來(lái)對(duì)Web服務(wù)做一個(gè)調(diào)用測(cè)試。在測(cè)試前您必須保證數(shù)據(jù)庫(kù)里已經(jīng)有圖書信息。如果EJB和Web Application都部署好,您可以通過(guò)以下頁(yè)面來(lái)往數(shù)據(jù)庫(kù)里增加數(shù)據(jù):
http://localhost:8080/axis/insert_data.jsp
測(cè)試代碼如下:
例程8 測(cè)試Web服務(wù)
|
如果在控制臺(tái)里打印出某個(gè)圖書的名字,那么就驗(yàn)證了客戶端和服務(wù)端的部署是正確的。在進(jìn)行下面的工作前,請(qǐng)確保這個(gè)測(cè)試是成功的。
對(duì)于客戶端程序來(lái)說(shuō),業(yè)務(wù)代表直接和Web服務(wù)打交道,獲得Web服務(wù)返回的數(shù)據(jù),并做對(duì)應(yīng)的處理,然后把數(shù)據(jù)返回給GUI程序,GUI程序只負(fù)責(zé)數(shù)據(jù)顯示。業(yè)務(wù)代表的代碼如下:
例程9 JAXRPCDelegate業(yè)務(wù)代表
|
和第一篇文章介紹的JAXMDelegate一樣,JAXRPCDelegate 同樣實(shí)現(xiàn)了BookBusiness接口,BookBusiness接口是以前設(shè)計(jì)的接口,我們?cè)谶@里進(jìn)行重用,這樣的好處是BookClientGUI程序幾只要做很少的更改就可以運(yùn)行。
在BookGUI構(gòu)造方法里增加以下內(nèi)容:
例程10 更改BookGUI程序
|
好了,經(jīng)過(guò)以上的奮戰(zhàn),讓我們來(lái)看運(yùn)行的結(jié)果吧。
java com.hellking.webservice.BookClientGUI
運(yùn)行結(jié)果如圖4所示。
通過(guò)以上的介紹,相信讀者對(duì)JAX-RPC Web服務(wù)開發(fā)已經(jīng)有一個(gè)比較深刻的認(rèn)識(shí)。總結(jié)一下,使用JAX-RPC開發(fā)Web服務(wù)時(shí),主要有以下的工作:
- 服務(wù)端點(diǎn)定義;
- 服務(wù)描述;
- 服務(wù)端點(diǎn)實(shí)現(xiàn);
- 服務(wù)端點(diǎn)部署;
本文已經(jīng)介紹了把Servlet作為Web服務(wù)端點(diǎn)開發(fā)Web服務(wù)的全過(guò)程,下一篇將是把EJB作為Web服務(wù)端點(diǎn)來(lái)開發(fā)。
Apache axis User's Guides: http://ws.apache.org/axis/ Sun jwsdp-1_1-tutorial, http://java.sun.com/webservices/downloads/webservicestutorial.htmlhttp://www.ibm.com/developerworks/cn/xml/index.htmlXML & Web services專區(qū) JAX-RPC API http://java.sun.com/webservices Jwdp1.1 http://java.sun.com/webservices 下載 樣例代碼
關(guān)于作者 陳亞強(qiáng):北京華園天一科技有限公司高級(jí)軟件工程師,擅長(zhǎng)J2EE技術(shù),曾參與多個(gè)J2EE項(xiàng)目的設(shè)計(jì)和開發(fā),對(duì)Web服務(wù)有很大的興趣并且有一定的項(xiàng)目經(jīng)驗(yàn)。熱愛(ài)學(xué)習(xí),喜歡新技術(shù)。即將由電子工業(yè)出版社出版的《J2EE企業(yè)應(yīng)用開發(fā)》正在最終定稿階段,目前正從事J2EE方面的開發(fā)和J2EE Web服務(wù)方面的圖書寫作。您可以通過(guò) cyqcims@mail.tsinghua.edu.cn和他聯(lián)系。 |
posted on 2006-06-23 11:01 ASONG 閱讀(298) 評(píng)論(0) 編輯 收藏 所屬分類: webservice