第11章 将Ajax应用作为REST客户端

Ajax的正式定义:Ajax应用就是在web浏览器里运行的Web服务客户端。

Ajax应用的不利方面在于,每个应用状态都是同一个URI — 即最终用户访问的第一个URI。这破坏了可寻址性(addressability)和无状态性(statelessness)。虽然幕后的web服务也许是可寻址的和无状态的,但最终用户无法把一个特殊状态加入收藏夹,而且浏览器的后退按钮也失去了原有的作用。

利用 XMLHttpRequest 将XML文档解析成DOM对象,并通过 request.responseXML 来访问该DOM对象。

如何发送请求:
1, 构造一个XMLHttpRequest对象。 例如在Mozilla系列浏览器(例如FF)里,应该是这样的: Request = new XMLHttpRequest();

2,调用XMLHttpRequest.open方法,并传入跟请求有关的信息,其中前2个参数是可选的: request.open([HTTP method], [URI], true, [Basic auth username], [Basic auth password] );

其中第三个参数是用来控制浏览器进行异步操作的。

如果选择异步操作,必须设置一个回调函数: request.onReadyStateChange = [Name of handler function];
还可以用 setRequestHeader 方法为请求设置 HTTP 请求报头: request.setRequestHeader([Header name], [Header value]);

最后,通过调用 send 方法向 HTTP 服务器发送请求, 如果是 POST 或 PUT 请求,就应当把实体主体作为参数提交给 send 方法。如果是其他请求,就该该参数置为 null。

request.send([Entity-body]);
如果一切顺利的话,你的回调函数将被调用4次,而且每一次 request.readeyState 都有不同的值。当值等于4时,表明请求已经完成。可以处理响应了。

处理响应:

请求完成时,浏览器会最后一次调用你的回调函数。这时,有以下属性可供 XMLHttpRequest 实例读取。

State属性是数字状态代码。

responseXML 属性里是一个由解析响应文档而得到的 DOM 对象。要求服务器返回XML媒体类型。

responseText 属性里是响应文档的原始文本串。当服务器返回JSON或非XML格式的响应文档时,这个属性比较有用。

可以用getResponseHeader拿到响应包头的值。

Ajax应用可以通过重新实现“后退”与“前进”按钮,来挽回失去的无状态性。但不一定要缺乏创意地模仿浏览器的行为。

跨浏览器问题和Ajax库:针对不同的浏览器,实例化 XMLHttpRequest的方法是不同的。

以下是Bret Taylor编写的 JavaScript 函数。总是创建一个具有 XMLHttpRequest 功能的对象。 可以在他的网站(http://ajaxcookbook.org)上找到该函数。

	function createXMLHttpRequest() { 
		if ( typeof XMLHttpRequest != "undefined") { // typeof 运算符返回一个用来表示表达式的数据类型的字符串。
		return new XMLHttpRequest();
		} else if (typeof ActiveRequest != "undefined") {
			return new ActiveXObject("Microsoft.XMLHTTP");
		} else {
			throw new Error("XMLHttpRequest not supported");
		}
	}

相应的构造方法也该改为 Request = createXMLHttpRequest();

还有2个重要的跨浏览器问题。

首先,Safari浏览器不支持 PUT 和 DELETE方法。如果需要 Safari 能够访问你的服务,就得允许它们用重载的 POST 来模拟 PUT 和 DELETE 请求。

另外,IE会把成功获得的相应长期缓存下来。这样即使资源已经变化,用户也看不到资源的变化。规避此问题的最好方法是:服务器在返回表示时,同时附上适当的 ETag 响应报头,或者干脆用 Cache-Control 报头来禁用缓存。

颠覆浏览器安全模型:Web浏览器遵循这样一条基本规则,即防止来自一个域名的代码向另一个域名发送HTTP请求。可以采用2个方式来绕过此限制:请求代理和JoD。

请求代理:客户端向 example.com发送请求,在服务端向 yahoo.com 发送那些请求。

Yahoo 文档 ”Proxy for Cross-Domain XMLHttpRequest Calls“详细讲述了这一技术。 在这个技术中,在服务器预留一部分URI空间,用于模拟另一个服务URI空间。当收到一个对应该URI空间的请求时,把该请求转发给那个外部服务器,然后把外部服务器发送你的响应返回给客户端。

JavaScript on Demand:

JoD技术的基本想法是,HTML的 script 标签不一定非得包含写死的JavaScript代码。它可以通过 src 属性来引用位于另一个 URI 的代码。当 Web 浏览器遇到一个 script 标签时,它会加载 src 属性指定的外部脚本,并执行其中的代码。

正常的Web服务客户端可以在调用Web服务后,先查看它返回的表示,如果没有问题再对它进行处理。但假如是客户端提供可执行代码,而Web服务通过特殊手段来自动运行它的话,你就等于对它毫不设防了。

JoD只能发送GET请求。

用 src 属性来引用一个对象,要比用它来获取定制生成的 JavaScript 安全得多。 script 并非唯一可用于让浏览器加载表示的HTML标签。 img 和 frame 标签也可以。

第12章 REST式服务框架

REST 并不是一种架构,而是一种评判架构的方式。面向资源的架构是一种架构,它对设计加以约束,是你能够很容易地把问题划分为一个个REST式资源。

RoR的成功主要在于它的简单化假设。并不是提供了一大堆用以解决问题的工具,只是为你提供了一种用以解决各类常见问题的方式。

资源、控制器和视图每个Rails控制器可以暴露两种资源。你可以有一个”列表“或”工厂“资源(响应GET和POST请求)和 许多”对象“资源(响应GET、PUT和DELETE请求)。

返回的表示Rails可以根据客户端请求的目标URI或Accept报头决定返回哪个表示。

收到的表示
Rails的工作就是根据收到的表示生成一组关键字-值对,并以params hash 的形式来提供这些关键字-值对。

Rails/ROA 设计步骤
1,规划数据集
2,把数据集分配给一个个控制器
对于每一个控制器:
a,该控制器暴露的是一个列表或工厂资源吗?
b,该控制器暴露的是一组对象资源吗?
c,该控制器暴露的是一个用于创建或修改资源的表单资源吗?
对于列表和对象资源:
设计来自客户端的表示。
设计返回给客户端的表示。
把该资源与已有资源联系起来。
考虑有哪些典型的事件经过?
考虑可能出现哪些错误情况? 同样,这里常常可以采用基于数据库技术的应用的控制流。

Restlet的思想是 HTTP 客户端与 HTTP 服务端之间的差别,对于架构来说无所谓。一个软件应可以既充当Web客户端又充当Web服务端。

需要注意2点:
1,Web服务器的实际工作是由一个非常紧凑的、基于Simple框架的HTTP服务器连接器来处理的;
2,用强大的db4o 对象数据库来存储领域对象的。

Django的思想是:URI是一个Web应用的用户界面的一个重要部分,不应是自动生成的。Django让你从零开始设计URI。

Django框架的独特风格是:总在URI的末尾加一个斜杠。

urls.py也是采用URI模型的出现次序来依次比较的。和Rails不同的是,Django不用为我判断URI格式。

作为Django视图资源的实现

在Rails中,为了实现一个资源在统一接口幕后的行为,需要把代码放在controller中。 而在Django中,这些代码是放在view里的。



blog comments powered by Disqus

Published

10 October 2011

Tags