.NET调用JAVA的WebService方法
? 調(diào)用WebService,最簡單的辦法當(dāng)然是直接添加WEB引用,然后自動產(chǎn)生代理類,但是在調(diào)用JAVA的WebService時并沒有這么簡單,特別是對于SoapHeader的處理,在網(wǎng)上也有相關(guān)資料,但是都整理的不夠清晰明了。根據(jù)網(wǎng)上的資料,個人也對各種方法進行了嘗試,費了不少精力,為此特將自己的解決方法進行總結(jié)一下,以備以后需要以及相關(guān)朋友參考。
?
先說說的思路:
1、先用soapUI進行測試,這個工具會自動生成調(diào)用某個方法的XML。
2、把soapUI生成的XML作為模版,自己也生成一個一模一樣的XML并為參數(shù)節(jié)點賦好值。
3、將這個XML通過http直接發(fā)送給WebService。
4、接收返回的XML進行處理。
?
這樣做最大的好處就是可以自己很輕松的控制XML格式,最開始的時候我是通過添加引用的方式去調(diào)用某個方法一直失敗,但是用soapUI去測試這個方法又是可以成功調(diào)用的,折騰了半天,最后通過抓包的方式對發(fā)送的數(shù)據(jù)進行對比,發(fā)現(xiàn)兩者發(fā)送的XML相差甚遠,好了廢話不說了,就拿一個小實例來演示這個過程吧。
?
首先,通過soapUI工具測試調(diào)用WebService里公用的WebSercie(http://www.webxml.com.cn/WebServices/WeatherWebService.asmx)中的一個名為getSupportCity的方法,生成的XML如下:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://WebXml.com.cn/"><soapenv:Header/><soapenv:Body><web:getSupportCity><!--Optional:--><web:byProvinceName>北京</web:byProvinceName></web:getSupportCity></soapenv:Body> </soapenv:Envelope>
?
?上面加粗標(biāo)示的地方就是我們要修改賦值的地方,大家看到了吧,如果用添加引用自動生成代理類的方式,要產(chǎn)生這樣格式的XML有多難控制了吧,但是如果全部用代碼來生成也不是一件容易的事,個人用了一個比較巧妙的辦法:
在項目中添加一個名為“getSupportCity”的xml文件,將上面的XML粘貼上去,然后再將這個XML文件作為內(nèi)嵌資源(在這個的文件屬性里面的‘生產(chǎn)操作’選擇‘嵌入的資源’),使用的時候直接加載這個XML文件,然后按邏輯處理需要修改的地方(其實就是XML文檔操作)。使用內(nèi)嵌資源是為了不讓外面看到我們的那個XML文件,以防被修改了什么的。
?
下面看看調(diào)用的代碼實現(xiàn)吧:(為了理解方便清晰,我們用跟WebService上一模一樣的方法名和參數(shù))
/// <summary>/// 天氣預(yù)報/// </summary>/// <param name="id">居民id</param>public static void getPopCheckedInfo(){String ServerUrl = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";//得到WebServer地址Hashtable pars = new Hashtable();//用來存放參數(shù)pars["byProvinceName"] = "北京";XmlDocument xml = QuerySoapWebService(ServerUrl, "getSupportCity", pars);//這個是對返回的XML文件處理,我刪掉了,處理完后返回一個居民的實體對象 }
?
?WebSvcCaller.QuerySoapWebService方法代碼:
public static XmlDocument QuerySoapWebService(String URL, String MethodName, Hashtable Pars){HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);request.Method = "POST";request.Accept = @"gzip,deflate";request.ContentType = @"text/xml;charset=utf-8";request.UserAgent = @"Jakarta Commons-HttpClient/3.1";request.Credentials = CredentialCache.DefaultCredentials;request.Timeout = 10000;byte[] data = EncodeParsToSoap(Pars, MethodName);WriteRequestData(request, data);//將處理成字節(jié)組的XML寫到流中發(fā)送到服務(wù)端XmlDocument doc = new XmlDocument();doc = ReadXmlResponse(request.GetResponse());//讀取服務(wù)端返回的結(jié)果return doc;}
?
EncodeParsToSoap(Pars,?MethodName),處理XML文件方法的代碼:(以下僅供參考,大家根據(jù)自己的實際情況變動)
private static Hashtable hshtableXML = new Hashtable();/// <summary>/// 處理要發(fā)送的XML文檔/// </summary>/// <param name="Pars">參數(shù)</param>/// <param name="MethodName">方法名</param>private static byte[] EncodeParsToSoap(Hashtable Pars, String MethodName){XmlDocument xml = null;if (hshtableXML.ContainsKey(MethodName)){//如果已經(jīng)加載過,則從緩存中讀取xml = (XmlDocument)hshtableXML[MethodName];}else{//如果還未加載則進行加載,并放入緩存//從資源文件得到文件流Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("異步調(diào)用.file." + MethodName + ".xml");xml = new XmlDocument();xml.Load(stream);hshtableXML.Add(MethodName, xml);}//修改參數(shù)的值foreach (DictionaryEntry de in Pars){XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);nsmgr.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");nsmgr.AddNamespace("web", "http://WebXml.com.cn/");Hashtable subpars = de.Value as Hashtable;if (subpars == null){string subNode = "soapenv:Envelope/soapenv:Body/web:" + MethodName + "/web:" + de.Key.ToString();XmlNode node = xml.SelectSingleNode(subNode, nsmgr);node.InnerText = de.Value.ToString();}else{foreach (DictionaryEntry subde in subpars){string subNode = "soapenv:Envelope/soapenv:Body/ws:" + MethodName + "/" + de.Key.ToString() + "/" + subde.Key.ToString();XmlNode node = xml.SelectSingleNode(subNode, nsmgr);node.InnerText = subde.Value.ToString();}}}//將修改后的XML文件保存到流中//這樣做還可以保證發(fā)送的XML文件也是格式化的那種形式,而不是一整行//如通過OuterXml獲取的就是一整行,這樣也可能會導(dǎo)致服務(wù)端解析失敗,個人這次就碰到這種情況了MemoryStream outStream = new MemoryStream();xml.Save(outStream);byte[] buffer = new byte[outStream.Length];byte[] temp = outStream.GetBuffer();for (int i = 0; i < buffer.Length; i++){buffer[i] = temp[i];}outStream.Close();return buffer;}
?
最后還有WriteRequestData、ReadXmlResponse兩個方法的代碼:
/// <summary>/// 寫到流中,發(fā)送給服務(wù)端/// </summary>/// <param name="request">HttpWebRequest連接對象</param>/// <param name="data">要寫入連接流發(fā)給服務(wù)端的內(nèi)容</param>private static void WriteRequestData(HttpWebRequest request, byte[] data){request.ContentLength = data.Length;Stream writer = request.GetRequestStream();writer.Write(data, 0, data.Length);writer.Close();}/// <summary>/// 讀取服務(wù)端返回的結(jié)果/// </summary>private static XmlDocument ReadXmlResponse(WebResponse response){StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);String retXml = sr.ReadToEnd();sr.Close();XmlDocument doc = new XmlDocument();doc.LoadXml(retXml);return doc;}
注:在實際開發(fā)過程中,如果服務(wù)器不是標(biāo)準(zhǔn)的WebService,那么返回的數(shù)據(jù)格式不一定是XML,可能是很難解析的字符串,
出現(xiàn)這種情況解決辦法,
第一,讓服務(wù)器修改接口,返回標(biāo)準(zhǔn)XML格式;
第二:按字符串硬處理
?
?示例下載
參考文檔:
http://www.cnblogs.com/fengyao/archive/2010/06/14/1749383.html
轉(zhuǎn)載于:https://www.cnblogs.com/yxhblog/p/7207440.html
總結(jié)
以上是生活随笔為你收集整理的.NET调用JAVA的WebService方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 着急是谁唱的啊?
- 下一篇: Linux课堂随笔---第四天