.NET调用JAVA的WebService方法

      调用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如下:

ExpandedBlockStart.gif soapUI生成的XML
< 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文件方法的代码:(以下仅供参考,大家根据自己的实际情况变动)

ExpandedBlockStart.gif 处理XML文件方法的代码
         ///   <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#)

2、关于朗新WebServer接口问题

转载于:https://www.cnblogs.com/fengyao/archive/2010/06/14/1749383.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值