• .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里公用的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>

     上面加粗标示的地方就是我们要修改赋值的地方,大家看到了吧,如果用添加引用自动生成代理类的方式,要产生这样格式的XML有多难控制了吧,但是如果全部用代码来生成也不是一件容易的事,个人用了一个比较巧妙的办法:

    在项目中添加一个名为“getSupportCity”的xml文件,将上面的XML粘贴上去,然后再将这个XML文件作为内嵌资源(在这个的文件属性里面的‘生产操作’选择‘嵌入的资源’),使用的时候直接加载这个XML文件,然后按逻辑处理需要修改的地方(其实就是XML文档操作)。使用内嵌资源是为了不让外面看到我们的那个XML文件,以防被修改了什么的。

    下面看看调用的代码实现吧:(为了理解方便清晰,我们用跟WebService上一模一样的方法名和参数)

       /// <summary>
            /// 天气预报
            /// </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();//用来存放参数
                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);//将处理成字节组的XML写到流中发送到服务端
                XmlDocument doc = new XmlDocument();
                doc = ReadXmlResponse(request.GetResponse());//读取服务端返回的结果
                return doc;
            }

    EncodeParsToSoap(Pars, MethodName),处理XML文件方法的代码:(以下仅供参考,大家根据自己的实际情况变动)

     private static Hashtable hshtableXML = new Hashtable();
             /// <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("异步调用.file." + 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("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文件保存到流中
                //这样做还可以保证发送的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;
            }

    注:在实际开发过程中,如果服务器不是标准的WebService,那么返回的数据格式不一定是XML,可能是很难解析的字符串,

    出现这种情况解决办法,

    第一,让服务器修改接口,返回标准XML格式;

    第二:按字符串硬处理

     示例下载

    参考文档

    http://www.cnblogs.com/fengyao/archive/2010/06/14/1749383.html

  • 相关阅读:
    VMware workstation安装linux(ubuntu)配置详解
    虚拟机的三种网络模式
    虚拟机(VMware Workstation)的使用方法
    零基础学习hadoop到上手工作线路指导(初级篇)
    Hadoop到底能做什么?怎么用hadoop?
    什么是云计算技术
    什么是云计算
    静态数据库迁移
    apache-mysql-php安装与配置
    CentOS6.6下的authpuppy源码安装与配置完全纯净版,内有问题解答
  • 原文地址:https://www.cnblogs.com/yxhblog/p/7207440.html
Copyright © 2020-2023  润新知