webservice

来源:互联网 发布:创维25nd9000总线数据 编辑:程序博客网 时间:2024/05/29 14:03

WebService

Web服务有两层含义:1、是指封装成单个实体并发布到网络上的功能集合体;2、是指功能集合体被调用后所提供的服务。简单地讲,Web服务是一个URL资源,客户端可以通过编程方式请求得到它的服务,而不需要知道所请求的服务是怎样实现的,这一点与传统的分布式组件对象模型不同。

Web服务的体系结构是基于Web服务提供者Web服务请求者Web服务中介者三个角色和发布发现绑定三个动作构建的。简单地说,Web服务提供者就是Web服务的拥有者,它耐心等待为其他服务和用户提供自己已有的功能;Web服务请求者就是Web服务功能的使用者,它利用SOAP(信息交换的的协议)消息向Web服务提供者发送请求以获得服务;Web服务中介者的作用是把一个Web服务请求者与合适的Web服务提供者联系在一起,它充当管理者的角色,一般是UDDI(通用描述、发现与集成,它是一种独立于平台的,基于XML语言的用于在互联网上描述商务的协议。)。这三个角色是根据逻辑关系划分的,在实际应用中,角色之间很可能有交叉:一个Web服务既可以是Web服务提供者,也可以是Web服务请求者,或者二者兼而有之。显示了Web服务角色之间的关系:其中,“发布”是为了让用户或其他服务知道某个Web服务的存在和相关信息;“查找(发现)”是为了找到合适的Web服务;“绑定”则是在提供者与请求者之间建立某种联系。

图2-1 Web Service的体系结构

WebService的运行机理:

1:Web服务提供者设计实现Web服务,并将调试正确后的Web服务通过Web服务中介者发布,并在UDDI注册中心注册;(发布)

2:Web服务请求者(客户端)通过向Web服务中介者(URL或UDDI注册中心)请求特定的服务,中介者根据请求查询UDDI注册中心,为请求者寻找满足请求的服务; (发现)

3:Web服务中介者向Web服务请求者返回满足条件的Web服务描述信息,该描述信息用WSDL写成,各种支持Web服务的机器都能阅读;(发现)

4:客户端在WSDL文档的基础上生成一个代理类。客户端生成代理类的实例,通过代理类实例发送相应的SOAP消息给Web服务提供者的方式,以实现Web服务的调用;(绑定)

5:Web服务提供者解析SOAP消息并按SOAP消息执行相应的Web服务,并将服务结果同样以SOAP包的形式返回给Web服务请求者。(绑定)

 

 

什么是Web Services

从表面上看,Web Service 就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API(应用程序接口)。也就是说,可以利用编程的方法通过Web来调用这个应用程序。

对Web Service 更精确的解释: Web Services是建立可互操作的分布式应用程序的新平台。Web Service平台是一套标准,它定义了应用程序如何在Web上实现互操作性。你可以用任何你喜欢的语言,在任何你喜欢的平台上写Web Service ,只要我们可以通过Web Service标准对这些服务进行查询和访问。  
  不管你的Web Service是用什么工具,什么语言写出来的,只要你用SOAP协议通过HTTP来调用它,总体结构都一致。通常,你用你自己喜欢的语言(如VB 6或者VB.NET)来构建你的Web Service,然后用SOAP Toolkit或者.NET的内建支持来把它暴露给Web客户。于是,任何语言,任何平台上的客户都可以阅读其WSDL(描述语言)文档,以调用这个Web Service。客户根据WSDL描述文档,会生成一个SOAP请求消息。Web Service都是放在Web服务器 (如IIS) 后面的,客户生成的SOAP请求会被嵌入在一个HTTP POST请求中,发送到Web服务器来。Web服务器再把这些请求转发给Web Service请求处理器。请求处理器的作用在于,解析收到的SOAP请求,调用Web Service,然后再生成相应的SOAP应答。Web服务器得到SOAP应答后,会再通过HTTP应答的方式把它送回到客户端。

基本概念

SOAP(信息交换协议)

SOAP是web service的标准通信协议,SOAP为simple object access protocoll的缩写,简单对象访问协议. 它是一种标准化的传输消息的XML消息格式。

 

WSDL(Web Services Description Language)

WSDL的全称是webservice Description Language,是一种基于XML格式的关于web服务的描述语言。其主要目的在于web service的提供者将自己的web服务的所有相关内容,如所提供的服务的传输方式,服务方法接口,接口参数,服务路径等,生成相应的完全文档,发布给使用者。使用者可以通过这个WSDL文档,创建相应的SOAP请求消息,通过HTTP传递给webservice提供者;web服务在完成服务请求后,将 SOAP返回消息传回请求者,服务请求者再根据WSDL文档将SOAP返回消息解析成自己能够理解的内容。

 

UDDI的本质:服务的公共网址

将web service进行UDDI注册发布,UDDI是一种创建注册表服务的规范,以便大家将自己的web service进行注册发布供使用者查找.然而当服务提供者想将自己的web service向全世界公布,以便外部找到其服务时,那么服务提供者可以将自己的webservice注册到相应的UDDI商用注册网站,目前全球有IBM等4家UDDI商用注册网站。因为WSDL文件中已经给定了web service的地址URI,外部可以直接通过WSDL提供的URI进行相应的webservice调用。所以UDDI并不是一个必需的webservice组件,服务方完全可以不进行UDDI的注册。

什么时候使用Web Services

  Web Service是创建可互操作的分布式应用程序的新平台。Web Service 的主要目标是跨平台的可互操作性。为了达到这一目标,Web Service是完全基于XML、XSD等独立于平台、独立于软件供应商的标准的。Web Service在应用程序跨平台和跨网络进行通信的时候是非常有用的。Web Service适用于应用程序集成、B2B集成、代码和数据重用,以及通过Web进行客户端和服务器的通信的场合。  当然,Web Service也不是万能的,你不能到处滥用Web Service。在有些情况下,Web Service 会降低应用程序的性能,而不会带来任何好处。例如,一台机器或一个局域网里面运行的同构应用程序就不应该用Web Service 进行通信。

如何调用Web Services

客户端:取得服务端的服务描述文件WSDL,解析该文件的内容,了解服务端的服务信息,以及调用方式。根据需要,生成恰当的SOAP请求消息(指定调用的方法,已经调用的参数),发往服务端。等待服务端返回的SOAP回应消息,解析得到返回值。

服务端:生成服务描述文件,以供客户端获取。接收客户端发来的SOAP请求消息,解析其中的方法调用和参数格式。根据WSDL和WSML的描述,调用相应的COM对象来完成指定功能,并把返回值放入SOAP回应消息返回给用户。

高层接口:使用高层接口,不需要知道SOAP和XML(描述数据的标准方法)的任何信息,就可以生成和使用一个WebService。Soap Toolkit 2.0通过提供两个COM对象SoapClient和SoapServer,来完成这些功能。在客户端,只需要生成一个SoapClient实例,并用WSDL作为参数来调用其中的mssoapinit方法。SoapClient对象会自动解析WSDL文件,并在内部生成所有Web Service的方法和参数信息。之后,你就可以像调用IDispatch接口里的方法一样,调用里面所有的方法。在VB或是脚本语言里,你甚至可以直接在SoapClient对象名后面直接加上.方法(参数…)进行调用。

低层接口

要使用低层接口,你必须对SOAP和XML有所了解。你可以对SOAP的处理过程进行控制,特别是要做特殊处理的时候。在客户端,首先要创建一个HttpConnector对象,负责HTTP连接。设定Connector的一些头部信息,比如EndPoinURL和SoapAction等。如果网络连接需要使用代理服务器,那也要在这里设定相关的信息。接着创建SoapSerializer对象,用于生成Soap消息。按照WSDL里定义,把所有参数按顺序序列化,得到一个完整的SOAP请求消息。该Soap消息,作为Payload通过HttpConnector被发送到服务端。最后,生成一个SoapReader对象,负责读取服务端返回的SOAP消息,取得其中的返回值。

 
 调用webservice的方法
 
一:通过添加web服务引用的方式(建议调试时使用)
 
输入webservice地址,如:http://www.xxx.com/service.asmx.然后引用即可(注意:web引用名将作为加入webservice命名空间
 
二:通过添加dll引用
 1:输入http://www.xxx.com/service.asmx?wsdl打开后,另存为Service1.wsdl
2:使用wsdl工具将Service1.wsdl转换成为标准的C#文件—cs文件
定位到wsdl.exe目录:
cd\ C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin
或者直接打开Microsoft Visual Studio 2010->Visual Studio Tools->Visual Studio 20010 命令提示窗口
生成代理类cs文件
wsdl /l:cs /n:SiteAService /out:siteA.cs Service1.wsdl(Service1.wsdl可以是你的WebService URL,也可以是保存的Service1.wsdl文件)
 说明:
 /l参数指定生成的文件类型,本例中用cs表示生成C#文件
/n参数指定最后生成的代理程序所属的Namespace(命名空间)
/out参数设定输出的C#文件名
3:编译cs文件为dll
定位到csc.exe目录:
cd\ C:\WINDOWS\Microsoft.NET\Framework\v3.5
编译为dll:
csc /target:library /out:siteA.dll siteA.cs
4:引用dll
 三:动态调用(调用的服务是动态的,比如说在几个IIS中都有相同的一个服务,在运行时输入具体的IP才确定调用哪个服务)
传入服务服务网址,方法名和参数即可.
    using System;   
    using System.Net;   
    using System.IO;   
    using System.CodeDom;   
    using Microsoft.CSharp;   
    using System.CodeDom.Compiler;   
    using System.Web.Services.Description;   
    using System.Web.Services.Protocols;       
    namespace HB.Common   
    {   
        /* 调用方式   
         *   string url = "http://www.webservicex.net/globalweather.asmx" ;   
         *   string[] args = new string[2] ;   
         *   args[0] = "Hangzhou";   
         *   args[1] = "China" ;   
         *   object result = WebServiceHelper.InvokeWebService(url ,"GetWeather" ,args) ;   
         *   Response.Write(result.ToString());   
         */   
        public class WebServiceHelper   
        {   
            #region InvokeWebService   
            /// < summary>   
            /// 动态调用web服务   
            /// < /summary>   
            /// < param name="url">WSDL服务地址< /param>   
            /// < param name="methodname">方法名< /param>   
            /// < param name="args">参数< /param>   
            /// < returns>< /returns>   
            public static object InvokeWebService(string url, string methodname, object[] args)   
            {   
                return WebServiceHelper.InvokeWebService(url, null, methodname, args);   
            }       
            /// < summary>   
            /// 动态调用web服务   
            /// < /summary>   
            /// < param name="url">WSDL服务地址< /param>   
            /// < param name="classname">类名< /param>   
            /// < param name="methodname">方法名< /param>   
            /// < param name="args">参数< /param>   
            /// < returns>< /returns>   
            public static object InvokeWebService(string url, string classname, string methodname, object[] args)   
            {   
                string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";   
                if ((classname == null) || (classname == ""))   
                {   
                    classname = WebServiceHelper.GetWsClassName(url);   
                }        
                try   
                {   
                    //获取WSDL   
                    WebClient wc = new WebClient();   
                    Stream stream = wc.OpenRead(url + "?WSDL");   
                    ServiceDescription sd = ServiceDescription.Read(stream);   
                    ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();  //创建客户端代理代理类。
                    sdi.AddServiceDescription(sd, "", "");  //添加WSDL文档。 
                    CodeNamespace cn = new CodeNamespace(@namespace);   //命名空间
     
                    //生成客户端代理类代码   
                    CodeCompileUnit ccu = new CodeCompileUnit();   
                    ccu.Namespaces.Add(cn);   
                    sdi.Import(cn, ccu);   
                    CSharpCodeProvider icc = new CSharpCodeProvider();   
     
                    //设定编译参数   
                    CompilerParameters cplist = new CompilerParameters();   
                    cplist.GenerateExecutable = false;   
                    cplist.GenerateInMemory = true;   
                    cplist.ReferencedAssemblies.Add("System.dll");   //输出程序集的名称
                    cplist.ReferencedAssemblies.Add("System.XML.dll");   
                    cplist.ReferencedAssemblies.Add("System.Web.Services.dll");   
                    cplist.ReferencedAssemblies.Add("System.Data.dll");   
     
                    //编译代理类   
                    CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);   
                    if (true == cr.Errors.HasErrors)   
                    {   
                        System.Text.StringBuilder sb = new System.Text.StringBuilder();   
                        foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)   
                        {   
                            sb.Append(ce.ToString());   
                            sb.Append(System.Environment.NewLine);   
                        }   
                        throw new Exception(sb.ToString());   
                    }       
                    //生成代理实例,并调用方法   
                    System.Reflection.Assembly assembly = cr.CompiledAssembly;   
                    Type t = assembly.GetType(@namespace + "." + classname, true, true);   
                    object obj = Activator.CreateInstance(t);   
                    System.Reflection.MethodInfo mi = t.GetMethod(methodname);   调用服务端的什么方法
               //上面是根据WebService地址,模似生成一个代理类,如果你想看看生成的代码文件是什么样子,可以用以下代码保存下来,默认是保存在bin目录下面
                TextWriter writer = File.CreateText("MyTest.cs"); 
                icc.GenerateCodeFromCompileUnit(unit, writer, null);
                writer.Flush();
                writer.Close();
 
                 //注:method.Invoke(o, null)返回的是一个Object,如果你服务端返回的是DataSet,这里也是用(DataSet)method.Invoke(o, null)转一下就行了
 
                    return mi.Invoke(obj, args);   
     
                    /*  
                    PropertyInfo propertyInfo = type.GetProperty(propertyname);  
                    return propertyInfo.GetValue(obj, null);  
                    */   
                }   
                catch (Exception ex)   
                {   
                    throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));   
                }   
            }   
     
            private static string GetWsClassName(string wsUrl)   
            {   
                string[] parts = wsUrl.Split('/');   
                string[] pps = parts[parts.Length - 1].Split('.');   
     
                return pps[0];   
            }   
            #endregion  
        }   
    } 
 
        返回时如果不是字符串,即强制转换,如返回是DataSet,则
        string[] args = new string[2] ;       
        args[0] = "Hangzhou";       
        args[1] = "China" ;       
        object result = WebServiceHelper.InvokeWebService(url ,"GetWeather" ,args) ;       
        DataSet DSRe=(DataSet)result;

四:URL Behavior 属性

  如果知道服务的方法和参数,只是调用的URL网址会随时变化,那么可以手工创建一个服务,添加上对应的的方法和传入参数,然后引入到项目中,就可以直接开发,在创建服务的实例化时,才修改对应的URL即可.

  例如服务中有个方法叫GetTax,那么就可以这样改:

GetTax.GetTax GetTax1 = new GetTax.GetTax();   
GetTax1.Url = "http://" + WebIp1 + "/pub_wa_gspsp1/gettax.asmx";//动态引入服务器   
DataSet DS1 = GetTax1.GetTaxMx(Bm1, OldBz, Fpl, SLx, StaDa, EndDa); //调用服务器返回开票数据