【webservice】Java JAX-WS和JAX-RS webservice
一、webservice請(qǐng)求的工作原理:
客戶端——> 閱讀WSDL文檔 (根據(jù)文檔生成SOAP請(qǐng)求) ——>發(fā)送到Web服務(wù)器——>交給WebService請(qǐng)求處理器——>處理SOAP請(qǐng)求——> 調(diào)用WebService——>生成SOAP應(yīng)答 ——> Web服務(wù)器通過(guò)http的方式交給客戶端
詳細(xì)描述如下:
無(wú)論使用什么工具/語(yǔ)言編寫(xiě)的webservice服務(wù)端,都可以使用soap協(xié)議,通過(guò)HTTP來(lái)調(diào)用,調(diào)用原理相同:創(chuàng)建webservice服務(wù)端,將其暴露給web客戶端。客戶端閱讀其wsdl文檔,根據(jù)wsdl描述文檔生成相應(yīng)的soap請(qǐng)求信息。客戶生成的soap請(qǐng)求信息會(huì)被嵌入到一個(gè)http請(qǐng)求并發(fā)送到部署webservice服務(wù)的web服務(wù)器(如IIS)。web服務(wù)器再將請(qǐng)求轉(zhuǎn)發(fā)給webservice請(qǐng)求處理器。webservice請(qǐng)求處理器用于解析收到的soap請(qǐng)求,調(diào)用webservice服務(wù),獲取soap應(yīng)答。web服務(wù)器得到soap應(yīng)答后,再通過(guò)http應(yīng)答的方式返回給客戶端。
WSDL、SOAP和UDDI一起工作,支持webservice和Internet上的其它服務(wù)、應(yīng)用程序和設(shè)備交互作用。UDDI提供了發(fā)布和定位web服務(wù)的功能,WSDL描述了web服務(wù),SOAP服務(wù)提供了傳輸協(xié)議。
補(bǔ)充兩個(gè)概念:
1、soap:簡(jiǎn)單地說(shuō)是一個(gè)通過(guò)http來(lái)傳輸xml數(shù)據(jù)的協(xié)議。
2、WSDL:web服務(wù)的接口定義語(yǔ)言,使用xml來(lái)描述web服務(wù)的標(biāo)準(zhǔn)。描述了如何訪問(wèn)具體的接口,包括三個(gè)屬性:
1)如何訪問(wèn)服務(wù):和服務(wù)交互的數(shù)據(jù)格式以及必要的協(xié)議;
2)服務(wù)在哪里:協(xié)議的相關(guān)地址,比如url等信息;
3)服務(wù)具有哪些功能:webservice中提供了哪些可以調(diào)用的方法;
二、Java中的三種webservice規(guī)范
java中共有三種webservice規(guī)范:JAXM&SAAJ、JAX-WS(JAX-RPC)、JAX-RS。
JAX-WS規(guī)范是一組xml web service的java API。
規(guī)范是一組API?
規(guī)范只是集成在java平臺(tái)里邊的API,這個(gè)API是用來(lái)實(shí)現(xiàn)不同風(fēng)格的JWS的。人們把這一套API叫做web服務(wù)規(guī)范。因?yàn)樗鼈兊脑O(shè)計(jì)目標(biāo)不一樣,JAX-WS是為實(shí)現(xiàn)基于soap協(xié)議的web service提供的API,soap協(xié)議比較強(qiáng)大。而JAX-RS是為基于REST設(shè)計(jì)風(fēng)格的web service提供的API。有了API,然后我們?cè)俳Y(jié)合一些框架就能夠很輕松的實(shí)現(xiàn)web service。
支持的框架:
支持JAX-WS服務(wù)規(guī)范的框架有:
CXF,Axis,Xfire,結(jié)合java語(yǔ)言均可實(shí)現(xiàn)JAX-WS。
支持JAX-RS服務(wù)規(guī)范的框架有:
CXF:Xfire和Celtix的合并
Jersey:sun公司的JAX-RS參考實(shí)現(xiàn)
RESTEasy:JBoss的JAX-RS項(xiàng)目
Restlet:也許是最早的REST框架了,在JAX-ES之前就有了
三、重點(diǎn)內(nèi)容兩種不同風(fēng)格的SOA(面向服務(wù)的體系結(jié)構(gòu))架構(gòu):JAX-WS && JAX-RS
補(bǔ)充;
REST服務(wù):
URL定位資源,用HTTP動(dòng)詞(GET、POST、DELETE、DELETE )描述操作。簡(jiǎn)單來(lái)講,就是可以用httprequest調(diào)用某個(gè)function。比如在瀏覽器里輸入 www.chx.site/api/guesswhoisawesome,就會(huì)調(diào)用后臺(tái)的某個(gè)function等到一個(gè)response(可以是json)。REST服務(wù)采用HTTP做傳輸協(xié)議,REST對(duì)于HTTP的利用分為以下兩種:資源定位和資源操作。
資源定位:
REST要求對(duì)資源定位更加準(zhǔn)確,如下:
非rest方式:http://ip:port/queryUser.action?userType=student&id=001
Rest方式:http://ip:port/user/student/001
REST方式表示互聯(lián)網(wǎng)上的資源更加準(zhǔn)確,但是也有缺點(diǎn),可能目錄的層級(jí)較多不容易理解。
資源操作:
利用HTTP的GET、POST、PUT、DELETE四種操作來(lái)表示數(shù)據(jù)庫(kù)操作的SELETE、UPDATE、INSERT、DELETE操作。
比如:
查詢學(xué)生方法:
設(shè)置HTTP的請(qǐng)求方法為GET,url如下:
http://ip:port/user/student/001
添加學(xué)生方法:
設(shè)置http的請(qǐng)求方法為PUT,url如下:
http://ip:port/user/student/001/張三/…
REST常用與資源定位,資源操作方式較少使用。REST是一種軟件架構(gòu)理念,現(xiàn)在被移植到web服務(wù)上,那么再開(kāi)發(fā)web服務(wù)的時(shí)候,偏于面向資源的服務(wù)使用REST。REST簡(jiǎn)單易用,效率高,SOAP成熟度較高,安全性較好。
注意:REST不是webservice,JAX-RS只是將REST設(shè)計(jì)風(fēng)格應(yīng)用到web服務(wù)開(kāi)發(fā)上。REST風(fēng)格的webservice不采用soap傳輸,直接采用http傳輸,可以返回xml或json。
jaxb:java xml binding,是 JAX-WS和JAX-RS底層使用的對(duì)象與XML之間轉(zhuǎn)換的工具。
JAX-WS:java TM API for XML-Based WedService,是針對(duì)webservices。
JAX-RS:java TM API for RESTful webservices,是針對(duì)RESTful HTTP Service。
JAX-WS是以動(dòng)詞為中心,指定的是每次執(zhí)行函數(shù)。是面向消息的,每次請(qǐng)求都需要指定請(qǐng)求的方法。(大力支持的廠商如BEA,IBM,MS基本都是開(kāi)發(fā)工具廠商,沒(méi)有開(kāi)發(fā)工具來(lái)做webservice會(huì)很繁瑣)
JAX-RS是以名詞為中心,每次執(zhí)行的時(shí)候指的是資源。是面向資源的。后來(lái)將網(wǎng)絡(luò)上的東西當(dāng)作一種資源,每次請(qǐng)求都是對(duì)該資源進(jìn)行操作,比如對(duì)資源的增刪改查。RESTFul是一種風(fēng)格而不是一個(gè)協(xié)議。它的理念就是:網(wǎng)絡(luò)上的所有事物都被抽象為資源,每個(gè)資源對(duì)應(yīng)一個(gè)唯一的資源標(biāo)識(shí)符。(大力支持的廠商如Google,Yahoo,亞馬遜等都是服務(wù)運(yùn)營(yíng)廠商,REST簡(jiǎn)潔好用,又能滿足絕大部分需求)
四、JAX-WS VS JAX-RS 對(duì)于REST風(fēng)格的web服務(wù)
JAX-WS適用于基于XML的web服務(wù),如SOAP。JAX-RS沒(méi)有相同的限制。
JAX-WS通常面向服務(wù)器到服務(wù)器與定義良好的契約(WSDL)的交互,通常當(dāng)服務(wù)和客戶端來(lái)自不同的組。這是非常耗費(fèi)資源的,因此對(duì)于網(wǎng)絡(luò)或客戶端設(shè)備能力不夠理想的客戶端到服務(wù)器交互是不可行的。
JAX-RS適用于客戶端到服務(wù)器的交互,盡管服務(wù)器到服務(wù)器是可以的。由于它幾乎沒(méi)有服務(wù)義務(wù),可以根據(jù)客戶的需求進(jìn)行調(diào)整。
JAX-RS API只提供代碼優(yōu)先的方法,而JAX-WS允許使用WSDL文件(通常推薦),代碼優(yōu)先(通常不推薦)和合同優(yōu)先。
JAX-RS 2.0引入了客戶端API,它是HTTPURLConnection的一個(gè)智能包裝,具有更多的映射能力,JAX-WS也是一個(gè)包裝器,但是它在參考實(shí)現(xiàn)中處理的數(shù)據(jù)只是XML。
JAX-RS具有創(chuàng)建API的優(yōu)勢(shì),這些API可以更簡(jiǎn)單的在不同的瀏覽器和移動(dòng)設(shè)備上創(chuàng)建和消化消息,即JSON結(jié)構(gòu)。它沒(méi)有引入信封的概念,并使用HTTP。它不引入加密或安全性,它使用HTTPS。
JAX-WS雖然在HTTPS上運(yùn)行,但是使用WS-SecurityPolicy等為安全性提供了額外的補(bǔ)充。此外,使用WSDL可以確定合同,并且使用ESB(如DataPower)在應(yīng)用程序之外進(jìn)行驗(yàn)證。
然而,使用RESTFul服務(wù)API類(lèi)似于像Ruby和Python這樣的元編程,這會(huì)延遲運(yùn)行時(shí)間的問(wèn)題,因?yàn)殡p方?jīng)]有達(dá)成一致的定義模式和技術(shù)上的強(qiáng)制執(zhí)行。因此,我不建議在任何地方使用RESTFul服務(wù),但是我會(huì)推薦使用它。如果我控制了雙方,那么當(dāng)您構(gòu)建使用靜態(tài)HTML/CSS/JS的web應(yīng)用程序并與RESTFul服務(wù)器通信時(shí),數(shù)據(jù)的交互就會(huì)變得簡(jiǎn)單便捷。
五、調(diào)用webservice服務(wù)
1、使用axis1調(diào)用webservice服務(wù)(org.apache.axis.client.Service)
基于Axis服務(wù)端的webservice客戶端實(shí)現(xiàn)
2、使用axis2調(diào)用webservice服務(wù)
2.1應(yīng)用RPC的方式進(jìn)行遠(yuǎn)程調(diào)用(org.apache.axis2.rpc.client.RPCServiceClient)
2.2使用AXIS2插件生成客戶端的方式調(diào)用(wsdl2java工具),使用wsdl2java把WSDL文件轉(zhuǎn)成本地類(lèi),然后像本地類(lèi)一樣使用,即可。參看本人如下博 客: 使用axis1.4生成webservice的客戶端代碼
3、使用http以及spring提供的方法進(jìn)行調(diào)用
最近在項(xiàng)目開(kāi)發(fā)中遇到一個(gè)問(wèn)題,在這里記錄一下:
最近遇到一個(gè)奇怪的webservice服務(wù),他們提供的請(qǐng)求報(bào)文和返回報(bào)文均為soap格式,如下:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:sys="http://sysinf.ngis.ai.com"><soap:Header/><soap:Body><sys:selectOfflineReasonUseAccount><sys:xml><![CDATA[<root><msgHead><requestId>1139792697</requestId><requestTime>2017-10-23 12:33:00</requestTime><source>EMOS</source><target>IPOSS</target></msgHead><msgBody><msgType>selectOfflineReasonUseAccount</msgType><block><account>09038140196</account><areaCode>0903</areaCode></block></msgBody></root>]]></sys:xml></sys:selectOfflineReasonUseAccount></soap:Body> </soap:Envelope>務(wù)地址( http://..*.:8081/services/NEService.wsdl ) 在瀏覽器可以正常打開(kāi)。
但是當(dāng) 我使用soupUI以soap協(xié)議的方式打開(kāi)他們提供的地址的時(shí)候,顯示“Error load”。
后面我又嘗試在soupUI中使用REST的形式打開(kāi),打開(kāi)正常。
我是用普通的請(qǐng)求soap協(xié)議webservice服務(wù)端的代碼去調(diào)用這個(gè)服務(wù),http響應(yīng)碼返回500,和如下錯(cuò)誤信息
<faultstring>Only SOAP 1.1 or SOAP 1.2 messages are supported in the system</faultstring>從報(bào)錯(cuò)信息我們可以大概猜測(cè)出,錯(cuò)誤出在soap調(diào)用版本上。
之后我又嘗試使用請(qǐng)求rest協(xié)議webservice服務(wù)端的代碼去調(diào)用,依舊沒(méi)有成功,這次沒(méi)有http響應(yīng)碼和任何錯(cuò)誤信息的返回,日志顯示“read timeout”。
接著我進(jìn)行第五次嘗試,使用AXIS2插件生成客戶端的方式去調(diào)用,生成的客戶端代碼如下:
調(diào)用代碼如下:
問(wèn)題完美解決。
從上面的報(bào)錯(cuò)信息我們知道錯(cuò)誤出在soap協(xié)議版本的問(wèn)題上,于是我就換了一種思路,更改我代碼中的soap協(xié)議版本,使用服務(wù)端可以接受的版本去調(diào)用,于是就出現(xiàn)了以下兩種客戶端調(diào)用方法:
public String sendWebServiceRequest(String requestXml, String wsdl,String targetNamespace, String method) throws ServiceException,MalformedURLException, RemoteException {logger.debug("requestXml ------------ " + requestXml);String responseXml = "";requestXml = xmlDel(requestXml).trim();logger.debug("進(jìn)去提供方法------:");PostMethod postMethod = new PostMethod(wsdl);byte[] b = requestXml.getBytes();InputStream is = new ByteArrayInputStream(b, 0, b.length); // RequestEntity re = new InputStreamRequestEntity(is, b.length, "text/xml; charset=UTF-8");RequestEntity re = new InputStreamRequestEntity(is, b.length, "application/soap+xml; charset=UTF-8");postMethod.setRequestEntity(re); // postMethod.addRequestHeader("SOAPAction", "");//正常的soap請(qǐng)求postMethod.addRequestHeader("Content-Type","application/soap+xml");//soap1.2HttpClient hh = new HttpClient();try {int resCode=hh.executeMethod(postMethod);logger.debug("rescode >>> " + resCode);responseXml = postMethod.getResponseBodyAsString();responseXml = StringEscapeUtils.unescapeXml(responseXml);//對(duì)返回的字符串進(jìn)行轉(zhuǎn)義postMethod.releaseConnection();//關(guān)閉連接} catch (IOException e) {e.printStackTrace();}finally{postMethod.releaseConnection();}logger.info("ResponseXml---------:" + responseXml);return responseXml;}public String sendWebServiceRequest(String requestXml, String wsdl,String targetNamespace, String method) throws ServiceException,MalformedURLException, RemoteException {logger.debug("requestXml ------------ " + requestXml);String responseXml = "";requestXml = xmlDel(requestXml).trim();logger.debug("進(jìn)去提供方法------:");PostMethod postMethod = new PostMethod(wsdl);byte[] b = requestXml.getBytes();InputStream is = new ByteArrayInputStream(b, 0, b.length);RequestEntity re = new InputStreamRequestEntity(is, b.length, "text/xml; charset=UTF-8");postMethod.setRequestEntity(re); // postMethod.addRequestHeader("SOAPAction", "");//正常的soap請(qǐng)求postMethod.addRequestHeader("Content-Type","text/xml");//soap1.1HttpClient hh = new HttpClient();try {int resCode=hh.executeMethod(postMethod);logger.debug("rescode >>> " + resCode);responseXml = postMethod.getResponseBodyAsString();responseXml = StringEscapeUtils.unescapeXml(responseXml);//對(duì)返回的字符串進(jìn)行轉(zhuǎn)義postMethod.releaseConnection();//關(guān)閉連接} catch (IOException e) {e.printStackTrace();}finally{postMethod.releaseConnection();}logger.info("ResponseXml---------:" + responseXml);return responseXml;}重點(diǎn)就在兩處注釋的地方,正常的soap協(xié)議的JAX-WS,可以用soapUI的soap格式進(jìn)行調(diào)用,使用上面注釋的代碼行也能調(diào)用。然而這個(gè)webservice服務(wù)需要在請(qǐng)求實(shí)體和請(qǐng)求方法頭中加入請(qǐng)求頭驗(yàn)證:Content-Type:application/soap+xml。我查了一些資料,Content-Type:text/xml是soap1.1,而Content-Type:application/soap+xml是soap1.2。
我們可以使用soapUI來(lái)獲取webservice的請(qǐng)求/響應(yīng)報(bào)文,以及可以測(cè)試webservice服務(wù)端是否能正常調(diào)用,除了soapUI之外,myeclipse也可以實(shí)現(xiàn)這一功能:
通過(guò)上一步會(huì)在瀏覽器打開(kāi)如下頁(yè)面:
有了soap請(qǐng)求報(bào)文和響應(yīng)報(bào)文,接下來(lái)我們就可以進(jìn)行webservice客戶端的開(kāi)發(fā)和使用了。
SOAP提升:
1.目前WebService的協(xié)議主要有SOAP1.1和1.2。
2.兩者的命名空間不同。
3.SOAP1.1版本與SOAP1.2版本在頭信息上存在差異。
3.1.SOAP1.1存在SOAPAction的請(qǐng)求頭。
3.2.SOAP1.2沒(méi)有SOAPAction的請(qǐng)求頭。
4.基于SOAP1.1生成的WSDL和基于SOAP1.2生成的WSDL也不一樣。
5.在CXF中兩種協(xié)議請(qǐng)求的方式也不一樣。
5.1 soap1.1為content-Type:text/xm;charset=UTF-8
5.2 soap1.2為content-Type:application/soap+xml;charset=UTF-8
命名空間:
Soap1.1的命名空間:
xmlns:soap=“http://schemas.xmlsoap.org/soap/envelope/“
Soap1.2 命名空間:
xmlns:soap=”http://www.w3.org/2003/05/soap-envelope“
SOAP1.1的HTTP請(qǐng)求頭:
POST /xe_cxf2.4_soap12_spring_web/ws/helloworldsoap12?wsdl HTTP/1.1
Content-Type: text/xml; charset=UTF-8
Accept: **
User-Agent: Apache CXF 2.4.0
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:6767
Connection: keep-alive
Content-Length: 214
SOAP1.2的請(qǐng)求頭:
POST /xe_cxf2.4_soap12_spring_web/ws/helloworldsoap12?wsdl HTTP/1.1
Content-Type: application/soap+xml; charset=UTF-8
Accept: /
User-Agent: Apache CXF 2.4.0
Cache-Control: no-cache
Pragma: no-cache
Host: localhost:6767
Connection: keep-alive
Content-Length: 214
SOAP1.1和1.2的WSDL文件的差別:
在定義Service部分差別如下:
Soap1.1是以:soap:address定義。
Soap1.2是以:soap12:address定義。
注意:jdk1.6不支持12形式的訪問(wèn)。
通過(guò)BindingType將項(xiàng)目轉(zhuǎn)到1.2:
在類(lèi)上面添加以下注解可以使用soap1.2的協(xié)議:
@BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)或在applicationContext.xml中使用binding
<jaxws:binding><soap:soapBinding version="1.2" /> </jaxws:binding>總結(jié)
以上是生活随笔為你收集整理的【webservice】Java JAX-WS和JAX-RS webservice的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 基于数据库的分布式锁实现
- 下一篇: 新疆出差——特色美食大合集