.NET調用JAVA的WebService方法


原文:https://www.cnblogs.com/fengyao/archive/2010/06/14/1749383.html

調用WebService,最簡單的辦法當然是直接添加WEB引用,然后自動產生代理類,但是在調用JAVA的WebService時並沒有這么簡單,特別是對於SoapHeader的處理,在網上也有相關資料,但是都整理的不夠清晰明了。根據網上的資料,個人也對各種方法進行了嘗試,費了不少精力,為此特將自己的解決方法進行總結一下,以備以后需要以及相關朋友參考。

 

先說說的思路:

1、先用soapUI進行測試,這個工具會自動生成調用某個方法的XML。

2、把soapUI生成的XML作為模版,自己也生成一個一模一樣的XML並為參數節點賦好值。

3、將這個XML通過http直接發送給WebService。

4、接收返回的XML進行處理。

 

這樣做最大的好處就是可以自己很輕松的控制XML格式,最開始的時候我是通過添加引用的方式去調用某個方法一直失敗,但是用soapUI去測試這個方法又是可以成功調用的,折騰了半天,最后通過抓包的方式對發送的數據進行對比,發現兩者發送的XML相差甚遠,好了廢話不說了,就拿一個小實例來演示這個過程吧。

 

首先,通過soapUI工具測試調用WebService里一個名為getPopCheckedInfo的方法,生成的XML如下:

soapUI生成的XML

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.pop.wsif.cogent.com/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-2" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>用戶名</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">密碼</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">qTW5ajMAEp4o9BiSvcczNA==</wsse:Nonce>
<wsu:Created>2010-05-24T07:02:10.531Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ws:getPopCheckedInfo>
<arg0>參數</arg0>
</ws:getPopCheckedInfo>
</soapenv:Body>
</soapenv:Envelope>

 上面三個用漢字標示的地方就是我們要修改賦值的地方,大家看到了吧,如果用添加引用自動生成代理類的方式,要產生這樣格式的XML有多難控制了吧,但是如果全部用代碼來生成也不是一件容易的事,個人用了一個比較巧妙的辦法:

在項目中添加一個名為“getPopCheckedInfo”的xml文件,將上面的XML粘貼上去,然后再將這個XML文件作為內嵌資源(在這個的文件屬性里面的‘生產操作’選擇‘嵌入的資源’),使用的時候直接加載這個XML文件,然后修改那3個節點的值就可以了(用戶名和密碼一般都預先確定的,也可以直接寫在XML文件里,調用的時候就只要對那一個參數賦值了)。使用內嵌資源是為了不讓外面看到我們的那個XML文件,以防被修改了什么的。

 

下面看看調用的代碼實現吧:(為了理解方便清晰,我們用跟WebService上一模一樣的方法名和參數)

 
        /// <summary>
        /// 根據居民id獲取該居民信息
        /// </summary>
        /// <param name="id">居民id</param>
        public static People getPopCheckedInfo(string id)
        {
            String ServerUrl = Config.GetWebServerURL();//得到WebServer地址
            Hashtable pars = new Hashtable();//用來存放參數
            pars["arg0"] = id;
            XmlDocument xml = WebSvcCaller.QuerySoapWebService(ServerUrl, "getPopCheckedInfo", pars);
            //這個是對返回的XML文件處理,我刪掉了,處理完后返回一個居民的實體對象
            return myPeople;
        }
 

 

 WebSvcCaller.QuerySoapWebService方法代碼:

 
        /// <summary>
        /// 通用WebService調用(Soap),參數Pars為String類型的參數名、參數值
        /// </summary>
        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);//將處理成字節組的XML寫到流中發送到服務端
            XmlDocument doc = new XmlDocument();
            doc = ReadXmlResponse(request.GetResponse());//讀取服務端返回的結果
            return doc;
        }
 

 

EncodeParsToSoap(Pars, MethodName),處理XML文件方法的代碼:(以下僅供參考,大家根據自己的實際情況變動)

處理XML文件方法的代碼

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> /// <summary>
/// 處理要發送的XML文檔
/// </summary>
/// <param name="Pars">參數</param>
/// <param name="MethodName">方法名</param>
private static byte[] EncodeParsToSoap(Hashtable Pars, String MethodName)
{
XmlDocument xml = null;
if (hshtableXML.ContainsKey(MethodName))
{//如果已經加載過,則從緩存中讀取
xml = (XmlDocument)hshtableXML[MethodName];
}
else
{//如果還未加載則進行加載,並放入緩存

//從資源文件得到文件流
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("你的項目的名稱.XML文件存放的文件夾." + MethodName + ".xml");
xml = new XmlDocument();
xml.Load(stream);
hshtableXML.Add(MethodName, xml);
}

//修改參數的值
foreach (DictionaryEntry de in Pars)
{
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("ws", "http://ws.pop.wsif.cogent.com/");
Hashtable subpars = de.Value as Hashtable;
if (subpars == null)
{
string subNode = "soapenv:Envelope/soapenv:Body/ws:" + MethodName + "/" + 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文件保存到流中
//這樣做還可以保證發送的XML文件也是格式化的那種形式,而不是一整行
//如通過OuterXml獲取的就是一整行,這樣也可能會導致服務端解析失敗,個人這次就碰到這種情況了
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>
        /// 寫到流中,發送給服務端
        /// </summary>
        /// <param name="request">HttpWebRequest連接對象</param>
        /// <param name="data">要寫入連接流發給服務端的內容</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>
        /// 讀取服務端返回的結果
        /// </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;
        }
 

 

 參考文章:

1、.Net下采用GET/POST/SOAP方式動態調用WebService的簡易靈活實現(C#)

 

 
分類:  WebService


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM