欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java調(diào)用WebService服務的四種方法總結(jié)

 更新時間:2021年11月25日 15:55:17   作者:大猩猩_7703  
WebService是一種跨編程語言、跨操作系統(tǒng)平臺的遠程調(diào)用技術(shù),已存在很多年了,很多接口也都是通過WebService方式來發(fā)布的,下面這篇文章主要給大家介紹了關(guān)于java調(diào)用WebService服務的四種方法,需要的朋友可以參考下

一、前言

本來不想寫這個的,因為網(wǎng)上類似的是在是太多了。但是想想自己前面段時間用過,而且以后可能再也沒機會用了。所以還是記錄一下吧。我這兒是以C語言生成的WebService為例。因為通常來說,兩個java端之間的互相通訊沒必要寫成WebService的方式,太麻煩。除非有一方已經(jīng)固定了是webService的方式(常見于牛逼的甲方)。而且就算寫成了WebService方式兩個java端直接調(diào)用也相對比較簡單,因為用java的話很多規(guī)范都是自動生成好的,而其他語言就不是這樣了,有時候?qū)Ψ綁焊筒皇钦_的規(guī)范,你還不能讓對方改?。。。。∥矣X得webService這個東西常用于不同語言編寫的服務器之間進行數(shù)據(jù)交互。因為是基于WSDL的。我知道的主要的方法有以下幾種(我這兒全部以C語言編寫的WebService做優(yōu)缺點比較):

二、簡介 ?

1、通過axis2將WebService提供的wsdl文件生成對應的java類,這樣就可以相當調(diào)用本地類一樣調(diào)用webService提供的接口。

??? 優(yōu)點:調(diào)用簡單,無需自己編寫太多的東西。

??? 缺點:大部分情況根據(jù)對應的webService生成的服務中地址是固定的,不易更改,而且生成的代碼過于龐大 ,不便于閱讀。同時必須得有webservice對應的的wsdl文件,不太可控。

2、通過RPC方式調(diào)用(推薦使用)

??? 優(yōu)點:自己編寫部分調(diào)用代碼,可靈活更換調(diào)用的路徑,適合分布式部署的服務器,只需要知道webservice服務的方法名、命名空間、以及對應的參數(shù)就好。

??? 缺點:部分特殊情況下可能可以調(diào)用成功,但是無法獲取返回值。稍后會進行說明。

3、通過HttpURLConnection進行調(diào)用,可用于補充第二種方法的不足之處。

??? 優(yōu)點:補充RPC方式的不足,代碼編寫量較少。

??? 缺點:(C語言的WebService服務)大部分時候要自己編寫輸入的報文頭,自己解析返回的報文。需要事先抓包查看報文。

4、通過httpclient調(diào)用。

??? 和HttpURLConnection原理一樣,只是用不同方法實現(xiàn)。優(yōu)缺點也差不多。

三、具體解析

第一種方式,首先得下載axis2的jar包,Axis2提供了一個wsdl2java.bat命令可以根據(jù)WSDL文件自動產(chǎn)生調(diào)用WebService的代碼。

?wsdl2java.bat命令可以在<Axis2安裝目錄>/bin目錄中找到。如果你配置了環(huán)境變量則可以在控制臺中用一下方式

環(huán)境變量\bin\wsdl2java,具體如下。

%AXIS2_HOME%\bin\wsdl2java -uri d:demo.wsdl -p client -s -o stub

如果沒有則自己鍵入到對應的位置執(zhí)行。wsdl2java -uri d:demo.wsdl -p client -s -o stub

其中,-url是對應WebService的wsdl位置,可以是本地的也可以是網(wǎng)絡的。-p是指定生成的類名。具體參數(shù)列表如下:

  • -o <path> : 指定生成代碼的輸出路徑
  • -a : 生成異步模式的代碼
  • -s : 生成同步模式的代碼
  • -p <pkg> : 指定代碼的package名稱
  • -l <languange> : 使用的語言(Java/C) 默認是java
  • -t : 為代碼生成測試用例
  • -ss : 生成服務端代碼 默認不生成
  • -sd : 生成服務描述文件 services.xml,僅與-ss一同使用
  • -d <databinding> : 指定databingding,例如,adb,xmlbean,jibx,jaxme and jaxbri
  • -g : 生成服務端和客戶端的代碼
  • -pn <port_name> : 當WSDL中有多個port時,指定其中一個port
  • -sn <serv_name> : 選擇WSDL中的一個service
  • -u : 展開data-binding的類
  • -r <path> : 為代碼生成指定一個repository
  • -ssi : 為服務端實現(xiàn)代碼生成接口類
  • -S : 為生成的源碼指定存儲路徑
  • -R : 為生成的resources指定存儲路徑

–noBuildXML : 輸出中不生成build.xml文件

–noWSDL : 在resources目錄中不生成WSDL文件

–noMessageReceiver : 不生成MessageReceiver類

生成完后可以在axis2的bin目錄下找到對應的文件。文件和同類.java文件要大很多,并且調(diào)用路徑是定死的(標紅部分),改起來麻煩,反正我是不喜歡這種方式。雖然不要自己寫,但是看著這么多行就不爽,太臃腫了。

調(diào)用方式如下。(方式應該有多種,沒有去深入研究)

package client;
	import javax.xml.namespace.QName;
	import org.apache.axis2.addressing.EndpointReference;
	import org.apache.axis2.client.Options;
	import org.apache.axis2.rpc.client.RPCServiceClient;
	public class TestAms {
		public static void main(String[] args) throws Exception  
	    {
			AmsStub1 stub=new AmsStub1();
			AmsStub1.SetAlarmServerCfgMsg setmsg= new AmsStub1.SetAlarmServerCfgMsg();
			//ServiceStub.SetAlarmServerCfgMsgResponse re=new ServiceStub.SetAlarmServerCfgMsgResponse();
			 String str="{\"name\":\"demo\",\"id\":21,\"code\":\"161021021040288690\"}";//對應的參數(shù)
			setmsg.setPAlarmCfgMsg(str); //設置參數(shù)
 
			String re=stub.setAlarmServerCfgMsg(setmsg).getResponse(); //調(diào)用并獲取返回值
			System.out.println(re);
	    }
	}	

我工作中遇到的全是C語言編寫的WebService,而且每個人編寫的都有些區(qū)別,很多人給你的wsdl并不能直接成功生成對應的java類,而且這種方法還有上述的一些缺點,所以我拋棄了這種方法。(上述列的代碼全是以前試驗時用過的,那時候是成功的,寫這個博客的時候我把所有能找到的wsdl全試著生成一遍,結(jié)果全部生成失敗。心塞)。

第二種RPC 方式,強烈推薦。

這種方式不多說,直接看代碼就懂了 。這是一個調(diào)用webService查詢設備在線數(shù)的。

public String getOnline(String url){
		int errCode=0;
		JSONObject resultJson=new JSONObject();
		String result="";
		Service service = new Service();
		Call call;
		try {
			call=(Call) service.createCall();
			QName opAddEntry = new QName("urn:demo", "GetOnlineInfo"); //設置命名空間和需要調(diào)用的方法名
			call.setTargetEndpointAddress(url); //設置請求路徑
			call.setOperationName("GetNcgOnlineInfo"); //調(diào)用的方法名
			call.setTimeout(Integer.valueOf(2000));		//設置請求超時    		
			call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//設置返回類型 
			result= (String) call.invoke(opAddEntry,new Object[]{});
			
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			System.out.println("查詢在線狀態(tài)1:"+e.getMessage());
			errCode=1;
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
                        System.out.println("查詢在線狀態(tài)2:"+e.getMessage());
			errCode=2;
		}
		resultJson.put("errCode", errCode);
	    resultJson.put("data", result);
 
		return resultJson.toString();
	}

里面注釋比較全。還有些別的設置也比較簡單,自己琢磨就知道了。例如編碼方式、解析時間等。

說說這種方式的問題吧。我在使用的時候遇到的是:和我對接的人編寫了兩個WebService。但是由于這兩個中有許多部分是相同的,他就把這兩個合并了,同時提供了兩個命名空間(具體怎么操作的我也不清楚),那么問題了,這其中有一個命名空間的所有方法我都能成功調(diào)用,但是都無法收到返回值。當時我就方了,開始還是好好的,怎么就突然不行了,于是我繼續(xù)執(zhí)行,查看報錯消息,同時抓包查看報文內(nèi)容。終于給我發(fā)現(xiàn)了問題。

下圖是返回結(jié)果報的錯,大體意識就是說我設置的命名空間和對方的命名空間不匹配。然后RPC解析就失敗了。

然后我利用Wireshark抓包,得到一下結(jié)果。可以看看出,我請求的是命名空間是 ns1="urn:ncg"(其余的都是wsdl默認自帶的)。可是我收到的返回報文就變了。變成了這樣的? xmlns:dag="http://tempuri.org/dag.xsd" xmlns:dag="urn:dag" xmlns:ncg="urn:ncg"? 足足有三個啊。RPC按照默認設置的 ns1="urn:ncg" 去解析,那肯定什么都解析不了的。所以只有自己去解析了。這種情況可以利用第三種或者第四種方式進行調(diào)用。

第三種:利用HttpURLConnection拼接和解析報文進行調(diào)用。

還是上面那個查詢設備的方法。只不過改了下。當然,我這是知道報文后的解決辦法。

public String ncgConnection(String url,String method){
		 URL wsUrl;
	        int errCode=0;
			JSONObject resultJson=new JSONObject();
			String result="";
			try {
				wsUrl = new URL(url+"/"+method);
				 HttpURLConnection conn = (HttpURLConnection) wsUrl.openConnection();
			        
			        conn.setDoInput(true);
			        conn.setDoOutput(true);
			        conn.setRequestMethod("POST");
			        conn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
			        conn.setConnectTimeout(2000);
			        conn.setReadTimeout(2000);
			        OutputStream os = conn.getOutputStream();
			        //請求體
			        
			        //<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><ns1:DeleteCascadeFromCms soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:ncg"><ncg-code-list xsi:type="xsd:string">["11241525"]</ncg-code-list></ns1:DeleteCascadeFromCms></soapenv:Body></soapenv:Envelope>
 
			        String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
			        		+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><ns1:"+method+" soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"urn:ncg\"/></soapenv:Body></soapenv:Envelope>";
			        os.write(soap.getBytes());
			        InputStream is = conn.getInputStream();
			        
			        byte[] b = new byte[1024];
			        int len = 0;
			        String s = "";
			        while((len = is.read(b)) != -1){
			            String ss = new String(b,0,len,"UTF-8");
			            s += ss;
			        }
                                 result=s.split("<response xsi:type=\"xsd:string\">")[1].split("</response>")[0];
			        
			        is.close();
			        os.close();
			        conn.disconnect();
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				System.out.println("通訊模塊1:"+e.getMessage());
				errCode=1;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				System.out.println("通訊模塊2:"+e.getMessage());
				errCode=2;
			}
			resultJson.put("errCode", errCode);
			resultJson.put("data", result);
	     
	        return resultJson.toString();
	}

正常來說,利用HttpURLConnection實現(xiàn)很多的調(diào)用不需要自己拼接請求頭和解析返回結(jié)果的(例如java端提供的一些action或者controller),可是在這兒調(diào)用WebService,確確實實的需要自己手寫。對比上面那個Wireshark抓包的結(jié)果可以發(fā)現(xiàn),在請求體部分按照對方提供的wsdl進行拼接,結(jié)果部分也進行相同的解析。可以正確獲得結(jié)果。

第四種,利用httpclient

簡單來說,httpClient可以算是加強版的HttpURLConnection,httpClient的API比較多,也比較穩(wěn)定,不容易擴展。HttpURLConnection比較輕量級,容易根據(jù)自己的需求進行擴展。但是穩(wěn)定性不如httpClient。

這種方法具體實現(xiàn)思路和HttpURLConnection一樣。只是有點小區(qū)別。代碼如下:

public void demo(String url){
		
		HttpClient httpClient=new HttpClient();
		PostMethod postMethod=new PostMethod();
		postMethod.setPath(url+"/ncg.wsdl"); //路徑和wsdl名
		
		String soap = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
        		+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><ns1:GetNcgOnlineInfo soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"urn:ncg\"/></soapenv:Body></soapenv:Envelope>";
       
		try {
			byte[] b=soap.getBytes("utf-8");
			
			InputStream is = new ByteArrayInputStream(b, 0, b.length);
			RequestEntity re = new InputStreamRequestEntity(is, b.length,
			                 "application/soap+xml; charset=utf-8");
			postMethod.setRequestEntity(re);
			int statusCode = httpClient.executeMethod(postMethod);
			
			String soapResponseData = postMethod.getResponseBodyAsString();
			
			postMethod.releaseConnection();
                        //解析
                        System.out.println(soapResponseData.split("<response xsi:type=\"xsd:string\">")[1].split("</response>")[0]);
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (HttpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

結(jié)果:我這兒沒有做更多的判斷,直接輸出,這種方式我以前其實并沒有用到。如果有需要可以更具返回的狀態(tài)判斷是否成功。如果你去抓包的話,你會發(fā)現(xiàn)這個會和上面HttpURLConnection抓的一樣。

????

總結(jié):調(diào)用webService很多程度上需要依賴對方編寫WebService是否嚴謹,如果足夠嚴謹,推薦使用RPC方式編寫,其余的更具實際情況進行選擇

總結(jié)

到此這篇關(guān)于java調(diào)用WebService服務的四種方法的文章就介紹到這了,更多相關(guān)java調(diào)用WebService服務內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis中<choose>標簽的用法說明

    mybatis中<choose>標簽的用法說明

    這篇文章主要介紹了mybatis中<choose>標簽的用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • springboot注解及GET、POST接口寫法

    springboot注解及GET、POST接口寫法

    springboot提供了@Contrller和@RestController注解,@Controller返回頁面和數(shù)據(jù)而@RestController返回數(shù)據(jù),本文重點介紹springboot注解及GET、POST接口寫法,感興趣的朋友一起看看吧
    2024-04-04
  • 詳解Spring Bean的循環(huán)依賴解決方案

    詳解Spring Bean的循環(huán)依賴解決方案

    這篇文章主要介紹了詳解Spring Bean的循環(huán)依賴解決方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 詳解MyBatis特性之動態(tài)SQL

    詳解MyBatis特性之動態(tài)SQL

    動態(tài) SQL 是 MyBatis 的強大特性之一,這篇文章我們將結(jié)合動態(tài)SQL完成更加復雜的 SQL 操作,文章通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • java基于雙向環(huán)形鏈表解決丟手帕問題的方法示例

    java基于雙向環(huán)形鏈表解決丟手帕問題的方法示例

    這篇文章主要介紹了java基于雙向環(huán)形鏈表解決丟手帕問題的方法,簡單描述了丟手帕問題,并結(jié)合實例形式給出了Java基于雙向環(huán)形鏈表解決丟手帕問題的步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2017-11-11
  • mybaties?plus?selectMaps和selectList的區(qū)別說明

    mybaties?plus?selectMaps和selectList的區(qū)別說明

    這篇文章主要介紹了mybaties?plus?selectMaps和selectList的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java判斷變量是否為空問題的方法總結(jié)

    Java判斷變量是否為空問題的方法總結(jié)

    項目中經(jīng)常遇到對象判空,下面這篇文章主要給大家介紹了關(guān)于Java判斷變量是否為空問題的方法,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2023-04-04
  • java對接Modbus協(xié)議代碼示例

    java對接Modbus協(xié)議代碼示例

    Modbus是一種串行通信協(xié)議,Modbus已經(jīng)成為工業(yè)領(lǐng)域通信協(xié)議的業(yè)界標準,并且現(xiàn)在是工業(yè)電子設備之間常用的連接方式,這篇文章主要給大家介紹了關(guān)于java對接Modbus協(xié)議的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • java實現(xiàn)監(jiān)控rtsp流轉(zhuǎn)flv方法實例(前端播放,前后端代碼都有)

    java實現(xiàn)監(jiān)控rtsp流轉(zhuǎn)flv方法實例(前端播放,前后端代碼都有)

    這篇文章主要給大家介紹了關(guān)于java實現(xiàn)監(jiān)控rtsp流轉(zhuǎn)flv的相關(guān)資料,文中介紹的是前端播放,前后端代碼都有,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-06-06
  • Spring中ApplicationContext的拓展功能詳解

    Spring中ApplicationContext的拓展功能詳解

    這篇文章主要介紹了Spring中ApplicationContext的拓展功能詳解,相對于BeanFactory來說,ApplicationContext除了提供BeanFactory的所有功能外,還有一些其他的功能,主要包括國際化支持、資源訪問、事件傳遞,需要的朋友可以參考下
    2024-01-01

最新評論