(本文于2010.10.01發(fā)表在《草根》雜志第四期,LAMP交流超級群(500人):106382633)
話說某日有見哥學社陳哥真人秀,在六體膜拜之后,鑒于之前也有看過REST的一些東東,于是便有了本文,正文如下:
REST(Representational State Transfer表述性狀態(tài)轉(zhuǎn)移)是一種體系架構(gòu),它為客戶端和服務(wù)器之間的數(shù)據(jù)交互提供了指導。它將客戶/服務(wù)器通信這種計算模型抽象到了Web層面。
REST最早是在Roy Thomas Fielding博士的博士論文中提出的,REST是一種針對網(wǎng)絡(luò)應(yīng)用的設(shè)計和開發(fā)方式,是一種風格,可以降低開發(fā)的復雜性,提高系統(tǒng)的可伸縮性。
REST強調(diào)如下的體系架構(gòu)概念。
1、網(wǎng)絡(luò)上的所有事物都被抽象為資源(resource);
2、每個資源對應(yīng)一個唯一的資源標識(resource identifier),
3、通過通用的連接器接口(generic connector interface)對資源進行操作;
4、對資源的各種操作不會改變資源標識;
5、所有的操作都是無狀態(tài)的(stateless)。
REST對于信息的核心抽象是資源,一個資源是一組實體的概念上的映射,而REST使用一個資源標識符來標識組件之間交互所涉及到的特定資源。REST連接器提供了訪問和操作資源的值集合的一個通用接口。在這里所有的操作中,它們都是無狀態(tài)的,這樣就不必在多個請求之間保存狀態(tài),不必考慮上下文的約束,從而允許服務(wù)器組件迅速釋放資源,并進一步簡化其實現(xiàn),從而提高系統(tǒng)的可伸縮性。
現(xiàn)在我們就一個簡單的示例演示下REST。
在我們的示例中以Javascript為客戶端,與HTTP服務(wù)器體系架構(gòu)配合工作,使用URL作為資源標識,并將HTTP作為連接器接口。
客戶端的代碼:
function rest() {
var XMLHttpFactories = [
function () {return new XMLHttpRequest()},
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
var xmlhttp = false;
for (var i = 0; i < XMLHttpFactories.length; i++) {
try {
xmlhttp = XMLHttpFactories[i]();
} catch (e) {
continue;
}
break;
}
// 建立XMLHttpRequest對象
this.xmlhttp = xmlhttp;
}
rest.prototype._get = function(url, data) {
var xmlhttp = this.xmlhttp;
xmlhttp.open ('GET', url + "&" + data, false);
xmlhttp.send (null);
return xmlhttp.responseText;
};
rest.prototype._post = function(url, data) {
var xmlhttp = this.xmlhttp;
xmlhttp.open ('POST', url, false);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xmlhttp.setRequestHeader ("Content-Length", data.length);
xmlhttp.send (data);
return xmlhttp.responseText;
};
rest.prototype.get = function(url, data) {
url = url += "?op=GET";
return this._get(url, data);
}
rest.prototype.post = function(url, data) {
url = url += "?op=POST";
return this._post(url, data);
}
rest.prototype.put = function(url, data) {
url = url += "?op=PUT";
return this._post(url, data);
};
rest.prototype.del = function(url, data) {
url = url += "?op=DELETE";
return this._get(url, data);
};
function t() {
var restobj = new rest();
document.write (restobj.get("http://localhost/test/service.php", "content=GET Content"));
document.write (restobj.post("http://localhost/test/service.php", "content=POST Content"));
document.write (restobj.put("http://localhost/test/service.php", "content=PUT Content"));
document.write (restobj.del("http://localhost/test/service.php", "content=DELETE Content"));
}
t();
如上所示,我們在客戶端創(chuàng)建XMLHttpRequest對象,并且通過這個對象實現(xiàn)通過HTTP對服務(wù)器的操作GET、PUT、POST和DELETE以檢索和修改資源。HTTP則把對每一個資源的操作都限制在了4個之內(nèi):GET、POST、PUT和DELETE。HTTP的這四個方法分別對應(yīng)我們常見的CRUD操作,具體對應(yīng)關(guān)系如下 :
C(Create) <==> POST
R(Read/Retrieve) <==> GET
U(Update) <==> PUT
D(Delete/Destroy) <==> DELETE
雖然HTTP提供了這4個方法,但是在某些情況下,PUT和DELETE方法是不可用的,于是我們在這里使用GET方法和POST方法進行替代。另外,在JS操作時,需要注意同源策略(Same Origin Policy,SOP),考慮跨域的問題。
服務(wù)端代碼:
<?php
/**
* REST后臺程序簡單示例
*/
class Resource {
public function get($request) {
echo 'content=', $request['content'], "; get resource Successful<br /> ";
}
public function post($request) {
echo 'content=', $request['content'], "; post resource Successful<br /> ";
}
public function put($request) {
echo 'content=', $request['content'], "; update resource Successful<br /> ";
}
public function delete($request) {
echo 'content=', $request['content'], "; delete resource Successful<br /> ";
}
}
$request = $_REQUEST;
$op = $request['op'];
$op = strtolower($op);
$ops = array(
'get' => 1,
'post' => 1,
'put' => 1,
'delete' => 1,
);
if (!isset($ops[$op])) {
die('input error!');
}
$resource = new Resource();
$resource-> $op($request);
?>
如上所示,是我們提供REST數(shù)據(jù)的服務(wù)器端的代碼。這里只是簡單的應(yīng)答請求,輸出標識內(nèi)容。
以上就是我們這個示例的全部了,在這個示例中,我們的整體架構(gòu)是基于最簡單的客戶端/服務(wù)器模式,客戶端使用Javascript,以Ajax實現(xiàn)。我們不需要使用PHP之類的語言生成客戶端的頁面,所有的客戶端的工作都交給Javascript去做,包括從服務(wù)器端讀取數(shù)據(jù),生成頁面內(nèi)容,頁面布局等等。在服務(wù)器端,我們需要做的是提供資源,針對客戶端的請求返回對應(yīng)的資源,此時的服務(wù)器是無狀態(tài)的。客戶與服務(wù)器之間的數(shù)據(jù)交換不依賴于服務(wù)器,由客戶端來維護狀態(tài)。
另外:REST只是一種體系架構(gòu)風格,它并沒有改變服務(wù)器,它改變的是我們的編碼風格。