【webservice】Java JAX-WS和JAX-RS webservice
一、webservice請求的工作原理:
客戶端——> 閱讀WSDL文檔 (根據(jù)文檔生成SOAP請求) ——>發(fā)送到Web服務(wù)器——>交給WebService請求處理器——>處理SOAP請求——> 調(diào)用WebService——>生成SOAP應(yīng)答 ——> Web服務(wù)器通過http的方式交給客戶端
詳細(xì)描述如下:
無論使用什么工具/語言編寫的webservice服務(wù)端,都可以使用soap協(xié)議,通過HTTP來調(diào)用,調(diào)用原理相同:創(chuàng)建webservice服務(wù)端,將其暴露給web客戶端。客戶端閱讀其wsdl文檔,根據(jù)wsdl描述文檔生成相應(yīng)的soap請求信息。客戶生成的soap請求信息會被嵌入到一個http請求并發(fā)送到部署webservice服務(wù)的web服務(wù)器(如IIS)。web服務(wù)器再將請求轉(zhuǎn)發(fā)給webservice請求處理器。webservice請求處理器用于解析收到的soap請求,調(diào)用webservice服務(wù),獲取soap應(yīng)答。web服務(wù)器得到soap應(yīng)答后,再通過http應(yīng)答的方式返回給客戶端。
WSDL、SOAP和UDDI一起工作,支持webservice和Internet上的其它服務(wù)、應(yīng)用程序和設(shè)備交互作用。UDDI提供了發(fā)布和定位web服務(wù)的功能,WSDL描述了web服務(wù),SOAP服務(wù)提供了傳輸協(xié)議。
補(bǔ)充兩個概念:
1、soap:簡單地說是一個通過http來傳輸xml數(shù)據(jù)的協(xié)議。
2、WSDL:web服務(wù)的接口定義語言,使用xml來描述web服務(wù)的標(biāo)準(zhǔn)。描述了如何訪問具體的接口,包括三個屬性:
1)如何訪問服務(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平臺里邊的API,這個API是用來實(shí)現(xiàn)不同風(fēng)格的JWS的。人們把這一套API叫做web服務(wù)規(guī)范。因為它們的設(shè)計目標(biāo)不一樣,JAX-WS是為實(shí)現(xiàn)基于soap協(xié)議的web service提供的API,soap協(xié)議比較強(qiáng)大。而JAX-RS是為基于REST設(shè)計風(fēng)格的web service提供的API。有了API,然后我們再結(jié)合一些框架就能夠很輕松的實(shí)現(xiàn)web service。
支持的框架:
支持JAX-WS服務(wù)規(guī)范的框架有:
CXF,Axis,Xfire,結(jié)合java語言均可實(shí)現(xiàn)JAX-WS。
支持JAX-RS服務(wù)規(guī)范的框架有:
CXF:Xfire和Celtix的合并
Jersey:sun公司的JAX-RS參考實(shí)現(xiàn)
RESTEasy:JBoss的JAX-RS項目
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動詞(GET、POST、DELETE、DELETE )描述操作。簡單來講,就是可以用httprequest調(diào)用某個function。比如在瀏覽器里輸入 www.chx.site/api/guesswhoisawesome,就會調(diào)用后臺的某個function等到一個response(可以是json)。REST服務(wù)采用HTTP做傳輸協(xié)議,REST對于HTTP的利用分為以下兩種:資源定位和資源操作。
資源定位:
REST要求對資源定位更加準(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),可能目錄的層級較多不容易理解。
資源操作:
利用HTTP的GET、POST、PUT、DELETE四種操作來表示數(shù)據(jù)庫操作的SELETE、UPDATE、INSERT、DELETE操作。
比如:
查詢學(xué)生方法:
設(shè)置HTTP的請求方法為GET,url如下:
http://ip:port/user/student/001
添加學(xué)生方法:
設(shè)置http的請求方法為PUT,url如下:
http://ip:port/user/student/001/張三/…
REST常用與資源定位,資源操作方式較少使用。REST是一種軟件架構(gòu)理念,現(xiàn)在被移植到web服務(wù)上,那么再開發(fā)web服務(wù)的時候,偏于面向資源的服務(wù)使用REST。REST簡單易用,效率高,SOAP成熟度較高,安全性較好。
注意:REST不是webservice,JAX-RS只是將REST設(shè)計風(fēng)格應(yīng)用到web服務(wù)開發(fā)上。REST風(fēng)格的webservice不采用soap傳輸,直接采用http傳輸,可以返回xml或json。
jaxb:java xml binding,是 JAX-WS和JAX-RS底層使用的對象與XML之間轉(zhuǎn)換的工具。
JAX-WS:java TM API for XML-Based WedService,是針對webservices。
JAX-RS:java TM API for RESTful webservices,是針對RESTful HTTP Service。
JAX-WS是以動詞為中心,指定的是每次執(zhí)行函數(shù)。是面向消息的,每次請求都需要指定請求的方法。(大力支持的廠商如BEA,IBM,MS基本都是開發(fā)工具廠商,沒有開發(fā)工具來做webservice會很繁瑣)
JAX-RS是以名詞為中心,每次執(zhí)行的時候指的是資源。是面向資源的。后來將網(wǎng)絡(luò)上的東西當(dāng)作一種資源,每次請求都是對該資源進(jìn)行操作,比如對資源的增刪改查。RESTFul是一種風(fēng)格而不是一個協(xié)議。它的理念就是:網(wǎng)絡(luò)上的所有事物都被抽象為資源,每個資源對應(yīng)一個唯一的資源標(biāo)識符。(大力支持的廠商如Google,Yahoo,亞馬遜等都是服務(wù)運(yùn)營廠商,REST簡潔好用,又能滿足絕大部分需求)
四、JAX-WS VS JAX-RS 對于REST風(fēng)格的web服務(wù)
JAX-WS適用于基于XML的web服務(wù),如SOAP。JAX-RS沒有相同的限制。
JAX-WS通常面向服務(wù)器到服務(wù)器與定義良好的契約(WSDL)的交互,通常當(dāng)服務(wù)和客戶端來自不同的組。這是非常耗費(fèi)資源的,因此對于網(wǎng)絡(luò)或客戶端設(shè)備能力不夠理想的客戶端到服務(wù)器交互是不可行的。
JAX-RS適用于客戶端到服務(wù)器的交互,盡管服務(wù)器到服務(wù)器是可以的。由于它幾乎沒有服務(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的一個智能包裝,具有更多的映射能力,JAX-WS也是一個包裝器,但是它在參考實(shí)現(xiàn)中處理的數(shù)據(jù)只是XML。
JAX-RS具有創(chuàng)建API的優(yōu)勢,這些API可以更簡單的在不同的瀏覽器和移動設(shè)備上創(chuàng)建和消化消息,即JSON結(jié)構(gòu)。它沒有引入信封的概念,并使用HTTP。它不引入加密或安全性,它使用HTTPS。
JAX-WS雖然在HTTPS上運(yùn)行,但是使用WS-SecurityPolicy等為安全性提供了額外的補(bǔ)充。此外,使用WSDL可以確定合同,并且使用ESB(如DataPower)在應(yīng)用程序之外進(jìn)行驗證。
然而,使用RESTFul服務(wù)API類似于像Ruby和Python這樣的元編程,這會延遲運(yùn)行時間的問題,因為雙方?jīng)]有達(dá)成一致的定義模式和技術(shù)上的強(qiáng)制執(zhí)行。因此,我不建議在任何地方使用RESTFul服務(wù),但是我會推薦使用它。如果我控制了雙方,那么當(dāng)您構(gòu)建使用靜態(tài)HTML/CSS/JS的web應(yīng)用程序并與RESTFul服務(wù)器通信時,數(shù)據(jù)的交互就會變得簡單便捷。
五、調(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)成本地類,然后像本地類一樣使用,即可。參看本人如下博 客: 使用axis1.4生成webservice的客戶端代碼
3、使用http以及spring提供的方法進(jìn)行調(diào)用
最近在項目開發(fā)中遇到一個問題,在這里記錄一下:
最近遇到一個奇怪的webservice服務(wù),他們提供的請求報文和返回報文均為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 ) 在瀏覽器可以正常打開。
但是當(dāng) 我使用soupUI以soap協(xié)議的方式打開他們提供的地址的時候,顯示“Error load”。
后面我又嘗試在soupUI中使用REST的形式打開,打開正常。
我是用普通的請求soap協(xié)議webservice服務(wù)端的代碼去調(diào)用這個服務(wù),http響應(yīng)碼返回500,和如下錯誤信息
<faultstring>Only SOAP 1.1 or SOAP 1.2 messages are supported in the system</faultstring>從報錯信息我們可以大概猜測出,錯誤出在soap調(diào)用版本上。
之后我又嘗試使用請求rest協(xié)議webservice服務(wù)端的代碼去調(diào)用,依舊沒有成功,這次沒有http響應(yīng)碼和任何錯誤信息的返回,日志顯示“read timeout”。
接著我進(jìn)行第五次嘗試,使用AXIS2插件生成客戶端的方式去調(diào)用,生成的客戶端代碼如下:
調(diào)用代碼如下:
問題完美解決。
從上面的報錯信息我們知道錯誤出在soap協(xié)議版本的問題上,于是我就換了一種思路,更改我代碼中的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請求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);//對返回的字符串進(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請求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);//對返回的字符串進(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)用。然而這個webservice服務(wù)需要在請求實(shí)體和請求方法頭中加入請求頭驗證:Content-Type:application/soap+xml。我查了一些資料,Content-Type:text/xml是soap1.1,而Content-Type:application/soap+xml是soap1.2。
我們可以使用soapUI來獲取webservice的請求/響應(yīng)報文,以及可以測試webservice服務(wù)端是否能正常調(diào)用,除了soapUI之外,myeclipse也可以實(shí)現(xiàn)這一功能:
通過上一步會在瀏覽器打開如下頁面:
有了soap請求報文和響應(yīng)報文,接下來我們就可以進(jìn)行webservice客戶端的開發(fā)和使用了。
SOAP提升:
1.目前WebService的協(xié)議主要有SOAP1.1和1.2。
2.兩者的命名空間不同。
3.SOAP1.1版本與SOAP1.2版本在頭信息上存在差異。
3.1.SOAP1.1存在SOAPAction的請求頭。
3.2.SOAP1.2沒有SOAPAction的請求頭。
4.基于SOAP1.1生成的WSDL和基于SOAP1.2生成的WSDL也不一樣。
5.在CXF中兩種協(xié)議請求的方式也不一樣。
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請求頭:
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的請求頭:
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形式的訪問。
通過BindingType將項目轉(zhuǎn)到1.2:
在類上面添加以下注解可以使用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的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于数据库的分布式锁实现
- 下一篇: 新疆出差——特色美食大合集