客户端和服务器通信可采用一种自定义协议。然而,SOAP为此提供了一种灵活的、易于扩展的和简单的方案。使用XMLHTTP对象,客户端浏览器可请求在服务器上执行一个ASP,并等候服务器的响应以继续。由于原始客户端网页没有卸载,所以对客户来说,整个过程都是透明的,而且速度一般都非常快。
下面通过几个示范网页来探讨该技术。由于只有Microsoft Internet Explorer 5和更高的版本才支持XMLHTTP,所以本章的例子要想正常工作,你的客户端必须满足这一最低要求。
考虑到扩展性,我不希望用一个查询字符串来传递SOAP请求,因为这个字符串的长度限制在2048字节以内。相反,我希望在HTTP标头中传递请求,它不存在这方面的限制。清单A演示了如何使用客户端JavaScript,通过HTTP标头向服务器发送基本信息。
SOAP的问题
为了提供清单A的功能,要向服务器发出一个SOAP请求。这种请求由以下4部分组成:
信封包含整个请求,并将包含的信息标识成一个SOAP请求。
包Schema描述了构成SOAP包的信息。
主体包含SOAP包。
包内含有和服务器请求有关的实际信息。
由于SOAP文档也是一个XML文档,所以它具有和任何XML文档一样的限制。其中最重要的就是文档必须“良构”(Well-formed),这意味着两件事情。
首先,良构XML文档中的标记必须封闭。为演示这一点,最简单的办法就是观察HTML和XHTML的区别。在XML文档中,所有标记都是容器标记。虽然对于<span>等容器标记来说,这不会造成问题,但对于<hr>等非容器标记,却必须予以留意。
有两个办法将非容器标记变成容器标记。第一个和最明显的办法就是为每个标记(例如<hr>)添加一个结束标记(例如</hr>)。另一个办法是使用自封闭的XML标记;换言之,<hr></hr>可简写成<hr />。还要记住,XML文档要区分大小写。所以,<hr></hr>是良构的,但<HR></hr>不是。
良构XML文档的第二个要求是必须用单引号或双引号来封闭属性。所以,虽然<input type=text name=stuff />是完全有效的HTML,但却不是良构的XHTML,必须改成<input type=@#text@# name=@#stuff@# />。
SOAP文档还具有其他大多数XML文档都没有一个限制,也就是必须用一个XML架构(XML Schema)来描述SOAP文档。架构是文档结构以及用XML编写的内容的一种抽象表示,宗旨是为XML解析器定义和描述文档的结构。
创建SOAP文档最简单的方式就是连接几个字符串。但是,这样做容易犯错。相反,更好的做法是使用MSXML XML文档对象模型(DOM)的方法来创建SOAP文档。以这种方式创建文档,可保证文档总是良构的。为此,我创建了6个JavaScript函数来封装MSXML的DOM对象,并创建一个SOAP文档来设置、获取、响应set或get会话变量请求,向服务器发送一个SOAP文档,以及解析一个SOAP文档。清单B给出了这些函数;在实际的ASP页中,则通过一个include语句来引用它们。
xmlDOM、fault和collection函数主要由其他函数调用。xmlDOM函数的作用是返回最新版本的MSXML XML DOM对象的一个实例。fault函数的作用是创建一个错误SOAP文档,指出发生了一个错误。collection则是一个类构造函数,它定义了一个JavaScript关联数组。
第4个函数是sessionSOAP,它也作为一个类构造函数使用,使开发者不必关心具体如何创建一个SOAP文档来处理会话变量。第5个函数是sessionVariable,它处理同服务器交互所需的XMLHTTP逻辑。第6个函数是sessionParser,它也是一个类构造函数,作用是解析一个会话变量SOAP文档,获取会话变量的键/值对。清单C展示了具体如何使用这些函数和类。
服务器端的情况
除了sessionSOAP和sessionVariable,客户端的JavaScript函数和类也可在服务器端使用。之所以这样设计,是为了避免分别编写客户端和服务器端函数来完成相同的任务。清单D显示了完整的SoapTestClient.asp页,它负责设置及获取会话变量。
本例完整演示了如何使用XMLHTTP、MSXML和SOAP来访问及更新服务器端信息。还可针对其他目的来使用这些技术,比如更新一个ASP网页而不进行常规的卸载/重载操作;由于减少了和服务器的通信,所以它有助于加快应用程序的速度。