Java webSerivce的使用看完你就明白了
茫茫人海千千萬萬,感謝這一秒你看到這里。希望我的文章對你的有所幫助!
愿你在未來的日子,保持熱愛,奔赴山海!
?? 前言
webService與我們常見的httpapi接口有什么區(qū)別呢?
- 不同協(xié)議:HTTPService基于http協(xié)議,而WebService基于soap協(xié)議;
- 處理數(shù)據(jù)效率不同:HTTPService效率較高,傳輸?shù)氖亲址?,而WebService是包裝成了更復(fù)雜的對象以致于能處理較復(fù)雜的數(shù)據(jù)類型;
- 是否可以跨域處理:HttpService方式不能處理跨域,如果調(diào)用一個其它應(yīng)用的服務(wù)就要用webService,就像我現(xiàn)在是調(diào)其他系統(tǒng)的服務(wù)。
?? 概述
?? 介紹下
WebService主要是通過SOAP協(xié)議在Web上提供的軟件服務(wù),使用WSDL文檔進(jìn)行說明,并通過UDDI進(jìn)行注冊。WebService是一種跨編程語言和跨操作系統(tǒng)平臺的遠(yuǎn)程調(diào)用技術(shù),能使得運行在不同機(jī)器上的不同應(yīng)用無須借助附加的、專門的第三方軟件或硬件, 就可相互交換數(shù)據(jù)或集成。依據(jù)WebService規(guī)范實施的應(yīng)用之間, 無論它們所使用的語言、 平臺或內(nèi)部協(xié)議是什么, 都可以相互交換數(shù)據(jù)。
所以呢,如果你想是使用不同語言,不同平臺,不同地方,想進(jìn)行數(shù)據(jù)傳輸,自我推薦下,選擇WebService就沒錯的!
?? 多維度了解
- 從表面看,WebService就是一個應(yīng)用程序向外界暴露出一個能通過Web進(jìn)行調(diào)用的API,也就是說能用編程的方法通過Web來調(diào)用這個應(yīng)用程序。我們把調(diào)用這個WebService的應(yīng)用程序叫做客戶端,而把提供這個WebService的應(yīng)用程序叫做服務(wù)端。
- 從內(nèi)層看,WebService不是一種技術(shù),更像是建立在可互操作的分布式應(yīng)用程序的新平臺,是一個平臺,是一套標(biāo)準(zhǔn),是一種規(guī)范。它定義了應(yīng)用程序如何在Web上實現(xiàn)互操作性,你可以用任何你喜歡的語言,在任何你喜歡的平臺上寫WebService ,只要我們可以通過WebService標(biāo)準(zhǔn)對這些服務(wù)進(jìn)行查詢和訪問。
???????? 三個好兄弟
常伴于三個元素兄弟:UDDI,WSDL,SOAP
- UDDI:UDDI 是一種用于描述、發(fā)現(xiàn)、集成Web Service的技術(shù),它是Web Service協(xié)議棧的一個重要部分。通過UDDI,企業(yè)可以根據(jù)自己的需要動態(tài)查找并使用Web服務(wù),也可以將自己的Web服務(wù)動態(tài)地發(fā)布到UDDI注冊中心,供其他用戶使用。UDDI利用SOAP消息機(jī)制(標(biāo)準(zhǔn)的XML/HTTP)來發(fā)布,編輯,瀏覽以及查找注冊信息。它采用XML格式來封裝各種不同類型的數(shù)據(jù),并且發(fā)送到注冊中心或者由注冊中心來返回需要的數(shù)據(jù)。
- WSDL:是為了描述Web服務(wù)發(fā)布的XML格式。就是用機(jī)器能閱讀的方式提供的一個正式描述文檔而基于XML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個子集)的語言,用于描述WebService及其函數(shù)、參數(shù)和返回值。因為是基于XML的,所以WSDL既是機(jī)器可閱讀的,又是人可閱讀的。
- SOAP:簡單對象訪問協(xié)議,是交換數(shù)據(jù)的一種協(xié)議規(guī)范,是一種輕量的、簡單的、基于XML標(biāo)準(zhǔn)通用標(biāo)記語言下的一個子集)的協(xié)議。主要組成由Http協(xié)議和XML數(shù)據(jù)格式。WebService通過HTTP協(xié)議發(fā)送請求和接收結(jié)果時,發(fā)送的請求內(nèi)容和結(jié)果內(nèi)容都采用XML格式封裝,并增加了一些特定的HTTP消息頭,以說明HTTP消息的內(nèi)容格式,這些特定的HTTP消息頭和XML內(nèi)容格式就是SOAP協(xié)議。SOAP提供了標(biāo)準(zhǔn)的RPC(遠(yuǎn)程調(diào)用技術(shù))方法來調(diào)用WebService。
?? 選擇的好處
- 跨平臺調(diào)用。
- 跨語言調(diào)用。
- 遠(yuǎn)程調(diào)用。
?? 來開始使用吧
話不多說,看太多理論不如自己做個小demo測下來得爽快。所以Let's GO!
做一個天氣系統(tǒng)的demo,客戶端發(fā)送城市名稱,服務(wù)器端回應(yīng)相應(yīng)的天氣。
?? 創(chuàng)建一個空項目
創(chuàng)建一個空項目weatherServer出來,我使用的IDEA版本為2020.3版本。當(dāng)然一開始我比較詳細(xì)介紹啦
??實現(xiàn)發(fā)布服務(wù)端
1. 創(chuàng)建服務(wù)端模塊weatherServerTest
創(chuàng)建過程基本類似的。如果你想選擇使用我,那么我會提議你先創(chuàng)建一個服務(wù)端,這樣別人可以進(jìn)行訪問,或者使用他人的服務(wù)端都OK的啦。這里先會完成創(chuàng)建出一個服務(wù)端模塊出來,后續(xù)的創(chuàng)建客戶端模塊基本類似。這里我們直接選擇一個Maven項目即可,也可以自行選擇一個普通Java項目都行。JDK為流行的JDK8即可。
最終得到的空模塊服務(wù)端如下:
2. 提供天氣服務(wù)
接下來就是開發(fā)服務(wù)端代碼。提供簡單的城市天氣服務(wù)。
定義一個天氣業(yè)務(wù)接口IWeatherService
代碼如下:
package com.ws.service; public interface IWeatherSerice { /** * 通過城市名得到對應(yīng)的天氣 * @param city 城市 * @return 天氣 */ public String queryWeather(String city); }
編寫對應(yīng)的接口實現(xiàn)類WeatherServiceImpl
對應(yīng)的代碼如下:
package com.ws.service.impl; import com.ws.service.IWeatherSerice; import javax.jws.WebService; @WebService // 用該注解修改表示當(dāng)前類是一個服務(wù)類 必須加上的,不然啟動服務(wù)的時候會報錯。 public class WeatherServiceImpl implements IWeatherSerice { @Override public String queryWeather(String city) { // 這里直接返回對應(yīng)的城市和晴天?。。? return city + "的天氣為:晴天!"; } }
創(chuàng)建一個用于發(fā)布服務(wù)的類WeatherServerDemo。
對應(yīng)的代碼如下:
package com.ws.server; import com.ws.service.impl.WeatherServiceImpl; import javax.xml.ws.Endpoint; public class WeatherServerDemo { public static void main(String[] args) { /** * address: 服務(wù)地址 --> 提供訪問的地址 * implementor: 服務(wù)類 --> 提供訪問的接口的實現(xiàn)類 */ Endpoint.publish("http://localhost:8086/weatherServer", new WeatherServiceImpl()); System.out.println("服務(wù)發(fā)布成功"); } }
運行main方法,開啟服務(wù):
可以看到控制臺,他沒有運行完成后關(guān)閉,并且顯示服務(wù)發(fā)布成功了。接下來就在線看看我們發(fā)布的服務(wù)。
3. 訪問服務(wù)
訪問剛才提供的訪問的地址加上?wsdl,如:http://localhost:8086/weatherServer?wsdl
那如何看這個wsdl文檔呢?不怕,讓我來教你看幾個重要的部分就一目了然啦!注意:wsdl文檔需要從下往上看
- :服務(wù)視圖名稱,WebService的服務(wù)端點
- :Web Services的通信協(xié)議,還描述Web Services的方法、輸入、輸出。
- :描述了WebService可執(zhí)行的操作,通過binding指向portType
- :描述了服務(wù)中發(fā)布的方法,包括參數(shù),返回值等。
- :定義了WebService中使用的數(shù)據(jù)類型
訪問一個詳細(xì)的參數(shù)頁面:http://localhost:8086/weatherServer?xsd=1
?? 實現(xiàn)客戶端訪問的幾種方式
1. 創(chuàng)建客戶端模塊weatherClientTest
結(jié)構(gòu):
2. 生成對應(yīng)的客戶端代碼
為什么需要下載客戶端代碼,首先前面兩個方式需要用到服務(wù)端代碼的接口,然后如果你是訪問遠(yuǎn)程的服務(wù)端,那你也就訪問不了。
這里會介紹jdk自帶的命令:wsimport
wsimport是jdk自帶的webservice客戶端工具,可以根據(jù)wsdl文檔生成客戶端調(diào)用代碼(java代碼).
wsimport.exe位于JAVA_HOME\bin目錄下
常用參數(shù)為:
-d<目錄> - 將生成.class文件。默認(rèn)參數(shù)。
-s<目錄> - 將生成.java文件。
-p<生成的新包名> -將生成的類,放于指定的包下
wsimport -s ./ http://localhost:8086/weatherServer?wsdl
生成步驟:
- 進(jìn)入到客戶端模塊的src的java目錄下
在該目錄中,進(jìn)入命令行模式,然后輸入wsimport -s ./ http://localhost:8086/weatherServer?wsdl
,下載剛才啟動的服務(wù)端代碼。注意:這一步得保證服務(wù)端是啟動可訪問狀態(tài)。
最終生成代碼的結(jié)構(gòu)在IDEA結(jié)構(gòu)為:
? 這里得到的代碼跟wsdl文檔對應(yīng)的名稱可以一一對應(yīng)。當(dāng)然如果你想改包名的話,可以使用-p參數(shù)。
3. 客戶端訪問方式1
第一種方式:通過得到的代碼,service方式調(diào)用。
結(jié)構(gòu)如下:
代碼如下:
package com.ws.client; import com.ws.service.impl.WeatherServiceImpl; import com.ws.service.impl.WeatherServiceImplService; public class WeatherClientDemo1 { public static void main(String[] args) { // 1. 創(chuàng)建服務(wù)視圖 WeatherServiceImplService weatherServiceImplService = new WeatherServiceImplService(); // 2. 得到服務(wù)實現(xiàn)類 WeatherServiceImpl weatherService = weatherServiceImplService.getPort(WeatherServiceImpl.class); // 3. 調(diào)用接口的方法 String result = weatherService.queryWeather("廣州"); // 4. 返回遠(yuǎn)程訪問得到的結(jié)果 --> result = 廣州的天氣為:晴天! System.out.println("result = " + result); } }
最終我們運行后得到的結(jié)果也正如所預(yù)料的一般:
4. 客戶端訪問方式2
之前這一步有什么缺陷呢,應(yīng)該很清楚吧:我們固定了一個服務(wù)地址了,而且如果要改服務(wù)地址的話,可能還需要再生成一遍代碼。
所以我們把服務(wù)地址寫出來,結(jié)構(gòu)如下:
代碼如下:
package com.ws.client; import com.ws.service.impl.WeatherServiceImpl; import com.ws.service.impl.WeatherServiceImplService; import javax.xml.namespace.QName; import javax.xml.ws.Service; import java.net.MalformedURLException; import java.net.URL; public class WeatherClientDemo2 { public static void main(String[] args) throws Exception { // 1. 設(shè)置訪問的服務(wù)端地址 URL url = new URL("http://localhost:8086/weatherServer?wsdl"); /* 2.設(shè)置服務(wù)名稱和命名空間 namespaceURI: wsdl的命名空間(targetNamespace) localPart: 是服務(wù)視圖的名稱(service的name值) */ QName qName = new QName("http://impl.service.ws.com/", "WeatherServiceImplService"); // 3. 生成服務(wù)視圖 Service service = Service.create(url, qName); // 4. 得到服務(wù)視圖的實現(xiàn)類 --> WeatherServiceImpl WeatherServiceImpl weatherServiceImpl = service.getPort(WeatherServiceImpl.class); // 5. 調(diào)用接口方法得到結(jié)果! --> result = 深圳的天氣為:晴天! String result = weatherServiceImpl.queryWeather("深圳"); System.out.println("result = " + result); } }
這些對應(yīng)的參數(shù)在wsdl的那個位置呢? 看我指給你:
這第二種方式是比較常用的方式,首先推薦!
5. 客戶端訪問方式3
在不需要下載服務(wù)端代碼的,通過HTTPURLConnection的方式進(jìn)行訪問服務(wù)端。只是這里代碼就相對比較長啦,而且需要自行定義XML字符串和解析字符串。
在pom.xml文件中加入一個dom4j的依賴包
<dependencies> <dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.1.1</version> </dependency> </dependencies>
結(jié)構(gòu)如下:
創(chuàng)建對應(yīng)的測試demo,大概結(jié)構(gòu)如下:
代碼如下:可以復(fù)制到IDEA仔細(xì)觀看。
package com.ws.client; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Node; import java.io.DataOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Scanner; public class WeatherClientDemo3 { public static void main(String[] args) throws Exception { // 1. 設(shè)置訪問的服務(wù)端地址 URL url = new URL("http://localhost:8086/weatherServer?wsdl"); // 2.打開一個通向服務(wù)地址的連接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 3.設(shè)置參數(shù), --> POST必須大寫,否則拋出異常 connection.setRequestMethod("POST"); // 這里是text/xml不是text/html connection.setRequestProperty("content-Type", "text/xml;charset=utf-8"); // 4.設(shè)置輸入輸出,默認(rèn)是false沒有讀寫的權(quán)限 connection.setDoOutput(true); connection.setDoInput(true); // 5.組織SOAP數(shù)據(jù),發(fā)送請求 String soapXml = getXmlString("佛山"); System.out.println("soapXml = " + soapXml); // 6. 將數(shù)據(jù)寫入到輸出流中 DataOutputStream dos = new DataOutputStream(connection.getOutputStream()); dos.write(soapXml.getBytes("utf-8")); dos.flush(); // 7. 判斷遠(yuǎn)程訪問是否成功,如果響應(yīng)碼為200即為成功 if (connection.getResponseCode() == 200) { // 8. 獲取相應(yīng)的輸入流,得到對應(yīng)的結(jié)果 InputStream ips = connection.getInputStream(); Scanner scanner = new Scanner(ips); StringBuffer buffer = new StringBuffer(); while (scanner.hasNextLine()) { buffer.append(scanner.nextLine()); } scanner.close(); // 得到為xml字符串 System.out.println("buffer = " + buffer); // 9. 解析xml字符串獲得返回的字符串 String xml = parseXmlToString(buffer); System.out.println("xml = " + xml); } } private static String parseXmlToString(StringBuffer buffer) { try { // 得到對應(yīng)的文檔對象 Document document = DocumentHelper.parseText(buffer.toString()); // "http://"從任意位置的節(jié)點上選擇名稱為 item 的節(jié)點。 Node node = document.selectSingleNode("http://return"); return node.getText(); } catch (DocumentException e) { e.printStackTrace(); } return null; } private static String getXmlString(String string) { String xml = "<?xml version=\"1.0\" ?>" + "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<S:Body>" + "<ns2:queryWeather xmlns:ns2=\"http://impl.service.ws.com/\">" + "<arg0>" + string + "</arg0>" + "</ns2:queryWeather>" + "</S:Body>" + "</S:Envelope>\""; return xml; } }
得到的結(jié)果:
可以看出,可以得到相對應(yīng)的結(jié)果。
6. 三種方式比較
- 第一種方法:它雖然代碼比較簡潔,但是耦合度較高,只能適用于當(dāng)前下載的服務(wù)端的地址。一般我們服務(wù)端啟動后,接口方法,參數(shù)這些都不會發(fā)生太大的變化。但是如果地址改變了也就需要重新下載服務(wù)端代碼。
- 第二種方式:在第一種方式的基礎(chǔ)上,將服務(wù)端訪問地址抽出來,這樣我們就可以在xml文件等配置文件中進(jìn)行配置對應(yīng)的服務(wù)訪問地址,一旦需要修改,只需修改配置文件的訪問地址即可。
- 第三種方式:它并不需要下載服務(wù)端代碼,通過HTTPURLConnection的方式去遠(yuǎn)程訪問服務(wù)端,但是需要自己去生成xml字符串,然后得到的結(jié)果也需要自己去解析出來。而一旦傳入的xml字符串參數(shù)錯了,就會響應(yīng)失敗,或者得到的字符串解析失敗的問題。
- 個人推薦第二種方式,下載服務(wù)端代碼,然后編寫訪問的服務(wù)端的地址和創(chuàng)建對應(yīng)的接口去調(diào)方法。無需編寫額外的xml字符串和解析字符串。
??優(yōu)缺點
??優(yōu)點
- 通過我們的客戶端第三種方式,就可以得知我是采用XML格式封裝數(shù)據(jù),并且XML它是跨平臺,并且不需要特定的語言編寫出來,所以我也是跨平臺的。
- 通過客戶端訪問的方式,我們可以得知服務(wù)端可以在遠(yuǎn)程,可以在本地,我們可以通過SOAP協(xié)議實現(xiàn)異地調(diào)用。
??? 缺點
因為我是采用XML格式封裝數(shù)據(jù)的嘛,所以在傳輸過程中,可能需要傳輸額外的標(biāo)簽,然而標(biāo)簽越來越大的話,導(dǎo)致webservice性能下降。
?? 使用場景
- 發(fā)布一個服務(wù)(對內(nèi)/對外),不考慮客戶端類型,不考慮語言,不考慮性能,建議使用WebService。
- 服務(wù)端已經(jīng)確定使用WebService,客戶端不能選擇,就必須使用WebService。
?? 不適用場景
- 在系統(tǒng)考慮性能情況下,不建議使用WebService。
- 同構(gòu)程序(一個公司中系統(tǒng)之間的接口)下不建議使用WebService,比如java用RMI(遠(yuǎn)程方法調(diào)用),不需要翻譯成XML的數(shù)據(jù)。
??總結(jié)
相信各位看官都對webService如何使用及其它的概念和一些知識點都有了稍稍的了解吧,不確定用到人的是否很多,這里只做入門練習(xí),當(dāng)然如果我們要整合到SpringBoot項目中,甚至我們可以集成相關(guān)依賴來使用webService,例如我們可以使用SpringBoot使用CXF集成WebService。那我們應(yīng)不應(yīng)該學(xué)習(xí)這一門技術(shù)呢?其實我覺得看需求,如果需要用到了,我們可以快速了解下,用一用小demo快速入門,接著使用集成CXF來整合到項目中,從而達(dá)到這門技術(shù)的應(yīng)用到實際項目中去!
我個人其實也沒有接觸過,只因項目中需要來調(diào)用這樣webService接口的需求,所以我也是剛?cè)腴T,而且現(xiàn)在各網(wǎng)頁接口基本都是基于http請求來做的,所以我們可以當(dāng)了解了解咯,走過路過,瞧一瞧,保證不吃虧呀?。。?/p>
讓我們也一起加油吧!本人不才,如有什么缺漏、錯誤的地方,也歡迎各位人才大佬評論中批評指正!當(dāng)然如果這篇文章確定對你有點小小幫助的話,也請親切可愛的人才大佬們給個點贊、收藏下吧,一鍵三連,非常感謝!
學(xué)到這里,今天的世界打烊了,晚安!雖然這篇文章完結(jié)了,但是我還在,永不完結(jié)。我會努力保持寫文章。來日方長,何懼車遙馬慢!
感謝各位看到這里!愿你韶華不負(fù),青春無悔!
到此這篇關(guān)于Java webSerivce的使用看完你就明白了的文章就介紹到這了,更多相關(guān)Java webSerivce內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java servlet結(jié)合Oracle搭建java的web開發(fā)環(huán)境
今天我將與大家分享一下我學(xué)JAVA WEB寫的一些小實例 ,我個人是不太喜歡書本上的晦澀的概念的,所以我花了更多的時間在一些應(yīng)用實例上,我覺得這樣的學(xué)習(xí)方式很適合我,由簡到繁,由淺入深2015-12-12為何修改equals方法時還要重寫hashcode方法的原因分析
這篇文章主要介紹了為何修改equals方法時還要重寫hashcode方法的原因分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Java反射機(jī)制原理、Class獲取方式以及應(yīng)用場景詳解
反射機(jī)制是JAVA的核心知識點之一,大多數(shù)框架的實現(xiàn)原理就是利用了反射機(jī)制,掌握反射機(jī)制會使你學(xué)習(xí)框架更加輕松高效,這篇文章主要給大家介紹了關(guān)于Java反射機(jī)制原理、Class獲取方式以及應(yīng)用場景的相關(guān)資料,需要的朋友可以參考下2022-04-04Springboot?No?bean?named?'XXXXX'?available?問
這篇文章主要介紹了Springboot?No?bean?named?'XXXXX'?available?問題解決方法,解決方法也很簡單,盡量規(guī)范類的命名,注解中指定bean名稱,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07使用Spring靜態(tài)注入實現(xiàn)讀取配置工具類新方式
這篇文章主要介紹了使用Spring靜態(tài)注入實現(xiàn)讀取配置工具類新方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02