.net 工程师(二)
一、常考的HTTP知识
参考资料:https://www.cnblogs.com/hyunbar/p/10393887.html
二、C#中try, catch, finally的执行顺序
1、首先明确一点,就是不管怎样,finally一定会执行,即使程序有异常,并且在catch中thorw 了 ,finally还是会被执行。
2、当try和catch中有return时,finally仍然执行。
3、finally是在return后面的表达式运算完之后执行的,在执行完return时 ,程序并没有跳出,而是进入到finally中继续执行,
如果在finally如果对返回值进行了重新赋值,分为两种情况:
(1)当返回值是值类型(包括string类型,虽然是引用类型,这是特殊的个例)时,返回的值不受影响,
就是在trycatch时,返回的值已经确定了。
public static string[] TestYinYong()
{
string[] arr = { "one", "two" };
try
{
throw new Exception();
}
catch (Exception)
{
return arr;
}
finally
{
arr[1] = "three";
}
}
此时返回的值是:{ "one", "three" };
4、finally中不能有return语句,编译都无法通过,提示:控制不能离开finally子句主体
三、C#中的lock关键字
MSDN的定义:
lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。
先来看看执行过程,代码示例如下:
假设线程A先执行,线程B稍微慢一点。线程A执行到lock语句,判断obj是否已申请了互斥锁,判断依据是逐个与已存在的锁进行object.ReferenceEquals比较(此处未加证实),如果不存在,则申请一个 新的互斥锁,这时线程A进入lock里面了。
这时假设线程B启动了,而线程A还未执行完lock里面的代码。线程B执行到lock语句,检查到obj已经申请了互斥锁,于是等待;直到线程A执行完毕,释放互斥锁,线程B才能申请新的互斥锁并执行
lock里面的代码。
接下来说一些该lock什么对象。
为什么不能lock值类型,比如lock(1)呢?lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,
每次lock的是装箱后的对象。lock其实是类似编译器的语法糖,因此编译器直接限制住不能lock值类型。
退一万步说,就算能编译器允许你lock(1),但是object.ReferenceEquals(1,1)始终返回false(因为
每次装箱后都是不同对象),也就是说每次都会判断成未申请互斥锁,这样在同一时间,别的线程照样能
够访问里面的代码,达不到同步的效果。同理lock((object)1)也不行。
那么lock("xxx")字符串呢?MSDN上的原话是:
锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串
都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用
程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。
通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,
则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线
程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。而且lock(this)
只对当前对象有效,如果多个对象之间就达不到同步的效果。
lock(typeof(Class))与锁定字符串一样,范围太广了。
某些系统类提供专门用于锁定的成员。例如,Array 类型提供 SyncRoot。许多集合类型也提供 SyncRoot。
而自定义类推荐用私有的只读静态对象,比如:
private static readonly object obj = new object();
为什么要设置成只读的呢?这是因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的
对象变了,object.ReferenceEquals必然返回false。
参考资料:https://www.cnblogs.com/jintianhu/archive/2010/11/19/1881494.html
四、C#中的线程池
1、线程池的概念
许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生。其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态。为了简 化对这些线程的管理,.NET框架为每一个进程提供了一个线程池,使应用程序能够根据需要来有效地利用多个线程。一个线程监视排到线程池的若干个等待操作的状态。当一个等待操作完成时,线程池中 的一个辅助线程就会执行对应的回调函数。线程池中的线程由系统进行管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元 中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在 一段时间之后创建另一个辅助线程。但线程的数目永远不会超过最大值。超过最大值的其他线程可以排队,但它们要等到其他线程完成后才启动。
2、线程池的应用范围
线程池特别适合于执行一些需要多个线程的任务。使用线程池能够优化这些任务的执行过程,从而提高吞吐量,它不仅能够使系统针对此进程优化该执行过程,而且还能够使系统针对计算机上的其他进程 优化该执行过程。如果需要启动多个不同的任务,而不想分别设置每个线程的属性,则可以使用线程池。
如果应用程序需要对线程进行特定的控制,则不适合使用线程池,需要创建并管理自己的线程。
在以下几种情况下,适合于使用线程池线程:
(1)不需要前台执行的线程。
(2)不需要在使用线程具有特定的优先级。
(3)线程的执行时间不易过长,否则会使线程阻塞。由于线程池具有最大线程数限制,因此大量阻塞的线程池线程可能会阻止任务启动。
(4)不需要将线程放入单线程单元。所有 ThreadPool 线程均不处于多线程单元中。
(5)不需要具有与线程关联的稳定标识,或使某一线程专用于某一任务。
3、ThreadPool类
在多线程的程序中,经常会出现两种情况:一种是在应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应,这一般使用ThreadPool(线程池)来解决;另一种情况是 在线程平时都处于休眠状态,只是周期性地被唤醒,这一般使用Timer(定时器)来解决。下面对ThreadPool类进行详细说明。
ThreadPool类提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。该类提供一个由系统维护的线程池(可以看作一个线程的容器),该容器需要Windows 2000以上系统支持,因为其中某些方法调用了只有高版本的Windows才有的API函数。
下面介绍一下该类所提供的方法,如表1所示。
方法 |
描述 |
BindHandle |
将操作系统句柄绑定到ThreadPool |
GetAvailableThreads |
检索由GetMaxThreads方法返回的最大线程池线程数和当前活动线程数之间的差值 |
GetMaxThreads |
检索可以同时处于活动状态的线程池请求的数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用 |
GetMinThreads |
检索线程池在新请求预测中维护的空闲线程数 |
QueueUserWorkItem |
将方法排入队列以便执行。此方法在有线程池线程变得可用时执行 |
RegisterWaitForSingleObject |
注册正在等待WaitHandle的委托 |
SetMaxThreads |
设置可以同时处于活动状态的线程池的请求数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用 |
SetMinThreads |
设置线程池在新请求预测中维护的空闲线程数 |
UnsafeQueueNativeOverlapped |
将重叠的 I/O 操作排队以便执行 |
UnsafeQueueUserWorkItem |
注册一个等待 WaitHandle 的委托 |
UnsafeRegisterWaitForSingleObject |
将指定的委托排队到线程池 |
通过以上方法,可以对线程池进行设置以及相应的操作,那么,我们什么时候使用线程池呢?我们在用Thread类调用线程时,一次只能使用一个线程来创建和删除线程,这种方式的建立和删除线程对CPU 的使用是很频繁的,为了节省CPU的负荷,可以使用线程池对线程进行操作,为了使读者更深入的了解Thread类与ThreadPool类的差别。
在以下情况下,应使用ThreadPool类:
- 要以最简单的方式创建和删除线程;
- 应用程序使用线程的性能要优先考虑。
- 在以下情况下,应使用Thread类:
- 要控制所创建线程的优先级;
- 希望所使用的线程维护其标识,该标识要与线程一起进行各种操作,经过许多不同的时间段;
- 所使用的线程的寿命较长。
ThreadPool类会在线程的托管池中重用已有的线程。使用完线程后,线程就会返回线程池,供以后使用。ThreadPool有25个可用的线程(每个处理器)。
在使用线程池时,一般调用ThreadPool类的QueueUserWorkItem方法。
用户并不需要自已建立线程,只需要把要进行的操作写成函数,然后作为参数传递给ThreadPool类的QueueUserWorkItem方法就行了,传递的方法是依靠WaitCallback代理对象,而线程的建立、管理、运 行等工作都是由系统自动完成的,用户无须考虑那些复杂的细节问题。ThreadPool类的用法:首先程序创建了一个ManualResetEvent对象,该对象就像一个信号灯,可以利用它的信号来通知其它线程
4、优缺点
线程池有那些优点:
1.在多线程中线程池可以减少我们创建线程,并合理的复用线程池中的线程。因为在线程池中有线程的线程处于等待分配任务状态。
2.不必管理和维护生存周期短暂的线程,不用在创建时为其分配资源,在其执行完任务之后释放资源。
3.线程池会根据当前系统特点对池内的线程进行优化处理。
线程池的缺点:
我们把任务交给线程池去完成后,无法控制线程的优先级,设置线程的一些名称等信息。[不过我们可以在放入线程池之前加一层来完善这些工作]
5、参数设置
1 int workerThreads, completionPortThreads; 2 3 ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); 4 Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads); 5 6 ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads); 7 Console.WriteLine("线程池根据需要创建的最少数量的辅助线程:{0}.线程池根据需要创建的最少数量的异步 I/O 线程:{1}", workerThreads, completionPortThreads); 8 9 //设置线程池默认参数 10 ThreadPool.SetMaxThreads(100, 100); 11 ThreadPool.SetMinThreads(2, 2); 12 13 ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); 14 Console.WriteLine("线程池中辅助线程的最大数目:{0}.线程池中异步 I/O 线程的最大数目:{1}", workerThreads, completionPortThreads); 15 16 ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads); 17 Console.WriteLine("线程池根据需要创建的最少数量的辅助线程:{0}.线程池根据需要创建的最少数量的异步 I/O 线程:{1}", workerThreads, completionPortThreads); 18 19 ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads); 20 Console.WriteLine("可用辅助线程的数目:{0}.可用异步 I/O 线程的数目:{1}", workerThreads, completionPortThreads);
参考资料:https://www.cnblogs.com/caokai520/p/4308380.html
参考资料:https://www.cnblogs.com/DonetRen/p/10167095.html
五、您要创建ASP.NET应用程序用于运行AllWin公司内部的Web站点,这个应用程序包含了50个页面。您想要配置这个应用程序以便当发生一个 HTTP代码错误时它可以显示一个自定义的错误页面给用户。您想要花最小的代价完成这些目标,您应该怎么做?
A、在这个应用程序的Global.asax文件中创建一个Application_Error过程去处理ASP.NET代码错误。
B、在这个应用程序的Web.config文件中创建一个applicationError节去处理ASP.NET代码错误。
C、在这个应用程序的Global.asax文件中创建一个CustomErrors事件去处理HTTP错误。
D、在这个应用程序的Web.config文件中创建一个CustomErrors节去处理HTTP错误。
E、在这个应用程序的每一页中添加一个Page指示符去处理ASP.NET 代码错误。
F、 在这个应用程序的每一页中添加一个Page指示符去处理ASP.NET HTTP错误。
答案:CD
六、window.onload,$(document).ready(function(){}),$(function(){…})
1、jQuery 事件 - ready() 方法
当 DOM(文档对象模型) 已经加载,并且页面(包括图像)已经完全呈现时,会发生 ready 事件。
由于该事件在文档就绪后发生,因此把所有其他的 jQuery 事件和函数置于该事件中是非常好的做法。正如上面的例子中那样。
ready() 函数规定当 ready 事件发生时执行的代码。
ready() 函数仅能用于当前文档,因此无需选择器。
允许使用以下三种语法:
语法 1
$(document).ready(function)
语法 2
$().ready(function)
语法 3
$(function)
2、window.onload和$(document).ready(function(){})的区别
1、执行时间上的区别:window.onload必须等到页面内(包括图片的)所有元素加载到浏览器中后才能执行。而$(document).ready(function(){})是DOM结构加载完毕后就会执行。
2、编写个数不同:window.onload不能同时写多个,如果有多个window.onload,则只有最后一个会执行,它会把前面的都覆盖掉。$(document).ready(function(){})则不同,它可以编写多个,并且每一个都会执行。
3、简写方法:window.onload没有简写的方法,$(document).ready(function(){})可以简写为$(function(){})。
另外:由于在$(document).ready()方法内注册的事件,只要DOM就绪就会被执行,因此可能此时元素的关联文件未下载完,例如与图片有关的HTML下载完毕,并且已经解析为DOM树了,但很有可能图片还未加载完毕,所以例如图片的高度和宽度这样的属性此时不一定有效。
要解决这个问题,可以使用JQuery中另一个关于页面加载的方法---load()方法。load()方法会在元素的onload事件中绑定一个处理函数。如果处理函数绑定在元素上,则会在元素的内容加载完毕后触发。如:$(window).load(function(){})=====window.onload = function(){}...
3、$(function(){}) 和 $(document).ready(function(){})
这两个方法的效果都是一样的,都是在dom文档树加载完之后执行一个函数,
七、OO问题
1、
1 public class A
2 {
3 public A()
4 {
5 Print();
6 }
7 public virtual void Print()
8 {
9
10 }
11 }
12 public class B : A
13 {
14 int x = 25;
15 int y;
16 public B()
17 {
18 y = -1;
19
20 }
21 public override void Print()
22 {
23 x = x + y;
24 y = x + 1;
25 Console.WriteLine("x={0},y={1}", x, y);
26 }
27 }
当使用 B b = new B(),输出:25,26
当使用 B b = new B(),b.Print() 输出: 24,25
八、asp.net身份验证
参考资料:https://www.cnblogs.com/lhws/articles/1827330.html
九、C#中using,new的意义
1、using 命名空间名字。
例如:
using System
2、using别名
using 别名 = 包括详细命名空间信息的具体的类型。
using aClass = NameSpace1.MyClass;
3、using语句
只要离开了这个代码段就自动调用这个类实例的Dispose
using (MemoryStream ms = new MemoryStream(arr)) { }
十、c#实现深拷贝
参考资料:http://www.cnblogs.com/yuilin/archive/2011/10/28/2227881.html
十一、throw和throw ex的区别
在C#中推荐使用throw;来抛出异常;throw ex;会将到现在为止的所有信息清空,认为你catch到的异常已经被处理了,只不过处理过程中又抛出新的异常,从而找不到真正的错误源。
throw的用法主要有以下几种:
第一种(不推荐使用,可惜很多人都一直这么用的,包括俺,嘻嘻),这样适用会吃掉原始异常点,重置堆栈中的异常起始点:
try { } catch (Exception ex) { throw ex; }
第二种,可追溯到原始异常点,不过编译器会警告,定义的ex未有使用:
try { } catch (Exception ex) { throw; }
第三种,不带异常参数的,这个同第二种其实一样,可捕获所有类型的异常,IDE不会告警:
try { } catch { throw; }
其实第二种和第三种用法,书上也是不建议使用的,一般要从小粒度的异常捕获开始,采用多个catch语句,大家就见仁见智吧。。。
第四种:经过对异常重新包装,但是会保留原始异常点信息。推荐使用。
try { } catch (Exception ex) { throw new Exception("经过进一步包装的异常", ex); }
例子:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 ExceptionClass ec = new ExceptionClass();
6
7 try
8 {
9 ec.ExceptionThrow1();
10 }
11 catch (Exception ex)
12 {
13 Console.WriteLine(ex.ToString());
14 }
15
16 Console.WriteLine("---------------------------------------------------------------------");
17
18 try
19 {
20 ec.ExceptionThrow2();
21 }
22 catch (Exception ex)
23 {
24 Console.WriteLine(ex.ToString());
25 }
26
27 Console.WriteLine("---------------------------------------------------------------------");
28
29 try
30 {
31 ec.ExceptionThrow3();
32 }
33 catch (Exception ex)
34 {
35 Console.WriteLine(ex.ToString());
36 }
37
38 Console.WriteLine("---------------------------------------------------------------------");
39
40 try
41 {
42 ec.ExceptionThrow4();
43 }
44 catch (Exception ex)
45 {
46 Console.WriteLine(ex.ToString());
47 }
48
49 Console.WriteLine("---------------------------------------------------------------------");
50
51 Console.ReadKey();
52 Console.WriteLine("------------");
53
54
55 }
56 }
57 /// <summary>
58 /// 该Class用来测试异常抛出时相关上下文栈的调用情况
59 /// </summary>
60 public class ExceptionClass
61 {
62 /// <summary>
63 /// 抛出异常方法
64 /// </summary>
65 public void ExceptionThrow1()
66 {
67 try
68 {
69 // 调用原始异常抛出方法来抛出异常
70 this.ExceptionMethod();
71 }
72 catch (Exception ex)
73 {
74 throw ex;
75 }
76 }
77
78 /// <summary>
79 /// 抛出异常方法1
80 /// </summary>
81 public void ExceptionThrow2()
82 {
83 try
84 {
85 this.ExceptionMethod();
86 }
87 catch (Exception ex)
88 {
89 throw;
90 }
91 }
92
93 /// <summary>
94 /// 抛出异常方法2
95 /// </summary>
96 public void ExceptionThrow3()
97 {
98 try
99 {
100 this.ExceptionMethod();
101 }
102 catch
103 {
104 throw;
105 }
106 }
107
108 /// <summary>
109 /// 抛出异常方法3
110 /// </summary>
111 public void ExceptionThrow4()
112 {
113 try
114 {
115 this.ExceptionMethod();
116 }
117 catch (Exception ex)
118 {
119 throw new Exception("经过进一步包装的异常", ex);
120 }
121 }
122
123 /// <summary>
124 /// 原始异常抛出方法
125 /// </summary>
126 private void ExceptionMethod()
127 {
128 throw new DivideByZeroException();
129 }
130 }
运行结果:
从运行的结果可以看到,第一种用法已经吃掉了原始异常信息。而其它3种用法都可以追溯到原始异常,推荐使用第四种用法
参考资料:http://www.cnblogs.com/JerryTian/archive/2012/09/24/2699459.html
十二、什么是webservice
一、什么是Web Service
1. 什么是Web Service呢?从表面上看,WebService就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API。这就是说,你能够用编程的方法通过Web调用来实现某个功能的应用程序。从 深层次上看,Web Service是一种新的Web应用程序分支,它们是自包含、自描述、模块化的应用,可以在网络(通常为Web)中被描述、发布、查找以及通过Web来调用。
2.Web Service便是基于网络的、分布式的模块化组件,它执行特定的任务,遵守具体的技术规范,这些规范使得Web Service能与其他兼容的组件进行互操作。它可以使用标准的互联网协议,像超文本传 输协议HTTP和XML,将功能体现在互联网和企业内部网上。WebService平台是一套标准,它定义了应用程序如何在Web上实现互操作性。你可以用你喜欢的任何语言,在你喜欢的任何平台上写Web Service。
3.WebService 为Internet 上的组件服务•通过网络提供,以URL 定位方法调用•以Internet技术为基础•未來的分散式应用程序
二、Web Service的标准
1. SOAP(Simple Object Access Protocol)
2. UDDI(UnviversalDescription ,Discovery,andIntegration) 统一描述发现和集成协议–公开的,或是企业自己的注册与查询
3. WSDL(Web Service Description Language)–WebService 描述语言
三、Web Service的标准
1. XMLWeb Service 通过标准的Web 协议向Web 用户提供有用的功能。多数情况下使用SOAP 协议。
2. XMLWeb Service 可以非常详细地说明其接口,这使用户能够创建客户端应用程序与它们进行通信。这种说明通常包含在称为Web 服务说明语言(WSDL)文档的XML 文档中。
3. XMLWeb Service 已经过注册,以便潜在用户能够轻易地找到这些服务,这是通过通用发现、说明和集成(UDDI)来完成的。
4.XMLWeb Service 体系结构的主要优点之一是:允许在不同平台上、以不同语言编写的各种程序以基于标准的方式相互通信。
5.我们将XMLWeb Service 定义为:通过SOAP 在Web 上提供的软件服务,使用WSDL 文件进行说明,并通过UDDI 进行注册。
四、SOAP
•Soap 是XML Web Service 的通信协议。
•SOAP 是一种规范,用来定义消息的XML 格式 。包含在一对SOAP 元素中的、结构正确的XML 段就是SOAP 消息。
•SOAP 规范的其他部分介绍如何将程序数据表示为XML,以及如何使用 SOAP 进行远程过程调用 (RPC)。这些可选的规范部分用于实现 RPC 形式的应用程序,其中客户端将发出一条 SOAP 消息(包含可调用函数,以及要传送到该函数的参数),然后服务器将返回包含函数执行结果的消息。目前,多数 SOAP 实现方案都支持 RPC 应用程序。SOAP 还支持文档形式的应用程序,在这类应用程序中,SOAP 消息只是 XML 文档的一个包装。文档形式的 SOAP 应用程序非常灵活,许多新的 XML Web Service 都利用这一特点来构建使用 RPC 难以实现的服务
五、SOAP
•SOAP 规范的最后一个可选部分定义了包含SOAP 消息 的 HTTP 消息的样式。此 HTTP 绑定非常重要,因为几乎所有当前的OS(以及许多以前的 OS)都支持HTTP. HTTP 绑定虽然是可选的,但几乎所有 SOAP 实现方案都支持HTTP 绑定,因为它是SOAP 的唯一标准协议。由于这一原因,人们通常误认为 SOAP 必须使用 HTTP。其实,有些实现方案也支持 MSMQ、MQ 系列、SMTP 或 TCP/IP 传输,但由于 HTTP 非常普遍,几乎所有当前的XML Web Service 都使用它。由于 HTTP 是 Web的核心协议,因此大多数组织的网络基础结构都支持HTTP。
• 到目前为止,SOAP 最引人注目的特征是它可以在许多不同的软件和硬件平台上实现。这意味着SOAP 可用于链接企业内部和外部的不同系统。
• HTTP 的普及和SOAP 的简单性使您几乎可以从任何环境调用它们,因此成为XMLWeb Service 的理想基础。 SOAP 的用户并不直接编写SOAP 消息,而是使用SOAP 工具包来创建和分析SOAP 消息。这些工具包通常将函数调用从某种语言转换为SOAP 消息。
五、UDDI
•UDDI 目录条目是介绍所提供的业务和服务的XML 文件。UDDI 目录条目包括三个部分。
“白页”介绍提供服务的公司:名称、地址、联系方式等等;
“黄页”包括基于标准分类法的行业类别;
“绿页”详细介绍了访问服务的接口,以便用户能够编写应用程序以使用 Web 服务。
服务的定义是通过一个称为类型模型(或 tModel)的 UDDI文档来完成的。多数情况下,tModel包含一个WSDL 文件,用于说明访问 XMLWeb Service 的SOAP 接口,但是tModel非常灵活,可以说明几乎所有类型的服务。
•UDDI 目录还包含若干种方法,可用于搜索构建您的应用程序所需的服务。例如,您可以搜索特定地理位置的服务提供商或者搜索特定的业务类型。之后,UDDI目录将提供信息、联系方式、链接和技术数据,以便您确定能满足需要的服务。
•UDDI 允许您查找提供所需的Web 服务的公司。如果您已经知道要与谁进行业务合作,但尚不了解它还能提供哪些服务,这时该如何处理呢?WS-Inspection规范(英文)允许您浏览特定服务器上提供的XML Web Service 的集合,从中查找所需的服务。
五、wsdl
•Web Service Description Language (WSDL):用来定义WebService交换的文件格式以及提供服务方式的说明文件
•WSDL 表示 Web服务说明语言,是一个 XML文档,用于说明一组 SOAP 消息以及如何交换这些消息。WSDL对于 SOAP 的作用就象TLD 对于Tiglib的作用。由于WSDL 是 XML 文档,因此很容易进行阅读和编辑;但大多数情况下,它由软件生成和使用。
•要查看 WSDL 的值,可以假设您要调用由您的一位业务伙伴提供的SOAP 方法。您可以要求对方提供一些 SOAP消息示例,然后编写您的应用程序以生成并使用与示例类似的消息。WSDL 通过明确的表示法指定请求消息必须包含的内容以及响应消息的样式。
•WSDL 文件用于说明消息格式的表示法以XML 架构标准为基础,这意味着它与编程语言无关,而且以标准为基础,因此适用于说明可从不同平台、以不同编程语言访问的XML Web Service 接口。除说明消息内容外,WSDL 还定义了服务的位置,以及使用什么通信协议与服务进行通信。WSDL 文件定义了编写使用 XML Web Service 的程序所需的全部内容。
•当前,许多 SOAP工具包都包括从现有程序接口生成 WSDL 文件的工具,但却几乎没有直接用于编写WSDL 的工具,而且 WSDL的工具支持也很不完整。但不久就会出现编写 WSDL 文件的工具,接着还会有生成代理和存根的工具(与 COMIDL 工具很相似),这些工具将成为多数SOAP 实现方案的一部分。到那时,WSDL将成为创建 XML Web Service 的 SOAP接口的首选方法。 •由W3C制定的标准