Web Service远程调用技术(RPC)的基本概念及实现方式。
前言
Web Service即web服务,是一种跨编程语言和跨操作系统平台的远程调用技术。Web服务包含了一套标准,例如HTTP、XML、SOAP、WSDL、UDDI等,定义了应用程序如何在Web上实现互操作,可以在任何支持这些标准的平台(如Windows、Linux)中使用。
Web Service与Web API相比,更加适合端到端的应用场景(C/S架构),适合作为内部服务使用。
基本概念
SOAP
SOAP即简单对象访问协议(Simple Object Access Protocol),是Web Service的通信协议,基于XML文件并绑定在HTTP协议上传递。SOAP消息包括Envelope、Header和Body元素。
一条SOAP消息就是一个普通的XML文档,文档包括下列元素:
- Envelope元素,必选,可把此XML文档标识为一条SOAP消息
- Header元素,可选,包含头部信息
- Body元素,必选,包含所有的调用和响应信息
WSDL
Web Service描述语言(SebService Definition Language,简称WSDL)就是用机器能阅读的方式提供的一个正式描述文档而基于XML的语言,用于描述Web Service及其函数、参数和返回值。
在WSDL说明书中,描述了
- 对外发布的服务名称(类)
- 接口方法名称(方法)
- 接口参数(方法参数)
- 服务返回的数据类型(方法返回值)
UDDI
UDDI(Universal Description,Discovery and Integration),也就是通用的描述、发现以及整合,是一套基于Web的、分布式的、为WebService提供的、信息注册中心的实现标准规范。用户可以通过UDDI来注册和搜索Web服务。
SOA架构
面向服务架构(Service Oriented Architecture,简称SOA),是一个组件模型,它将应用程序的不同功能单元(服务)通过预先定义的接口和契约联系起来。接口是采用中立的方式进行定义的,独立于实现服务的硬件平台、操作系统和编程语言,构建在系统中的服务以一种统一和通用的方式进行交互。
实现方式
注: 以下项目基于.NET Framework,.NET中无法使用
创建服务
使用ASP.NET Web应用程序(.NET Framework)创建一个Web服务(asmx文件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| using System.Web.Services;
namespace WebApplicationDemo { [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WebServiceTest : WebService { [WebMethod(Description = "测试方法")] public int Sum(int a, int b) { return a + b; } } }
|
调用服务
静态引用
根据提供的Web Service地址,通过Connected Services添加WCF Web服务引用,生成cs文件,然后直接调用。
1 2 3 4 5 6 7 8
| static void Main(string[] args) { WebServiceTestSoapClient client = new WebServiceTestSoapClient();
var res = client.SumAsync(1, 2);
Console.WriteLine(res.Result); }
|
反射调用
将Web Service地址存放到配置文件中,通过读取地址生成代理类,动态在项目中生成代理类文件,然后通过反射调用。
1 2 3 4 5 6
| static void Main(string[] args) { int res = (int)WebServiceProxy.InvokeWebService("https://localhost:44319/WebServiceTest.asmx", "WebServiceTest", "Sum", new object[] { 1, 2 });
Console.WriteLine(res); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
|
public class WebServiceProxy { public static object InvokeWebService(string url,string ns, string methodname, object[] args) { try { WebClient wc = new WebClient(); Stream stream = wc.OpenRead(url + "?WSDL"); ServiceDescription sd = ServiceDescription.Read(stream); string classname = sd.Services[0].Name; ServiceDescriptionImporter sdi = new ServiceDescriptionImporter(); sdi.AddServiceDescription(sd, "", ""); CodeNamespace cn = new CodeNamespace(ns);
CodeCompileUnit ccu = new CodeCompileUnit(); ccu.Namespaces.Add(cn); sdi.Import(cn, ccu); CSharpCodeProvider csc = new CSharpCodeProvider(); ICodeCompiler icc = csc.CreateCompiler();
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(ns + "." + classname, true, true); object obj = Activator.CreateInstance(t); System.Reflection.MethodInfo mi = t.GetMethod(methodname);
return mi.Invoke(obj, args); } catch { return null; } } }
|
参考文档