小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Web 服務(wù)編程,REST 與 SOAP

 xenophobe 2015-04-21

在 IBM Bluemix 云平臺(tái)上開發(fā)并部署您的下一個(gè)應(yīng)用。

現(xiàn)在就開始免費(fèi)試用

REST 簡(jiǎn)介

在開始我們的正式討論之前,讓我們簡(jiǎn)單看一下 REST 的定義。

REST(Representational State Transfer)是 Roy Fielding 提出的一個(gè)描述互聯(lián)系統(tǒng)架構(gòu)風(fēng)格的名詞。為什么稱為 REST?Web 本質(zhì)上由各種各樣的資源組成,資源由 URI 唯一標(biāo)識(shí)。瀏覽器(或者任何其它類似于瀏覽器的應(yīng)用程序)將展示出該資源的一種表現(xiàn)方式,或者一種表現(xiàn)狀態(tài)。如果用戶在該頁面中定向到指向其它資源的鏈接,則將訪問該資源,并表現(xiàn)出它的狀態(tài)。這意味著客戶端應(yīng)用程序隨著每個(gè)資源表現(xiàn)狀態(tài)的不同而發(fā)生狀態(tài)轉(zhuǎn)移,也即所謂 REST。

關(guān)于 REST 本身,本文就不再這里過多地討論,讀者可以參考 developerWorks 上其它介紹 REST 的文章。本文的重點(diǎn)在于通過 REST 與 SOAP Web 服務(wù)的對(duì)比,幫助讀者更深刻理解 REST 架構(gòu)風(fēng)格的特點(diǎn),優(yōu)勢(shì)。

回頁首

應(yīng)用場(chǎng)景介紹(在線用戶管理)

本文將借助于一個(gè)應(yīng)用場(chǎng)景,通過基于 REST 和 SOAP Web 服務(wù)的不同實(shí)現(xiàn),來對(duì)兩者進(jìn)行對(duì)比。該應(yīng)用場(chǎng)景的業(yè)務(wù)邏輯會(huì)盡量保持簡(jiǎn)單且易于理解,以有助于把我們的重心放在 REST 和 SOAP Web 服務(wù)技術(shù)特質(zhì)對(duì)比上。

需求描述

這是一個(gè)在線的用戶管理模塊,負(fù)責(zé)用戶信息的創(chuàng)建,修改,刪除,查詢。用戶的信息主要包括:

  • 用戶名(唯一標(biāo)志在系統(tǒng)中的用戶)
  • 頭銜
  • 公司
  • EMAIL
  • 描述

需求用例圖如下:

圖 1. 需求用例圖
REST

如圖 1 所示,客戶端 1(Client1)與客戶端 2(Client2)對(duì)于信息的存取具有不同的權(quán)限,客戶端 1 可以執(zhí)行所有的操作,而客戶端 2 只被允許執(zhí)行用戶查詢(Query User)與用戶列表查詢(Query User List)。關(guān)于這一點(diǎn),我們?cè)趯?duì) REST Web 服務(wù)與 SOAP Web 服務(wù)安全控制對(duì)比時(shí)會(huì)具體談到。下面我們將分別向您介紹如何使用 REST 和 SOAP 架構(gòu)實(shí)現(xiàn) Web 服務(wù)。

回頁首

使用 REST 實(shí)現(xiàn) Web 服務(wù)

本部分將基于 Restlet 框架來實(shí)現(xiàn)該應(yīng)用。Restlet 為那些要采用 REST 結(jié)構(gòu)體系來構(gòu)建應(yīng)用程序的 Java 開發(fā)者提供了一個(gè)具體的解決方案。關(guān)于更多的 Restlet 相關(guān)內(nèi)容,本文不做深入討論,請(qǐng)見參考資源列表。

設(shè)計(jì)

我們將采用遵循 REST 設(shè)計(jì)原則的 ROA(Resource-Oriented Architecture,面向資源的體系架構(gòu))進(jìn)行設(shè)計(jì)。ROA 是什么?簡(jiǎn)單點(diǎn)說,ROA 是一種把實(shí)際問題轉(zhuǎn)換成 REST 式 Web 服務(wù)的方法,它使得 URI、HTTP 和 XML 具有跟其他 Web 應(yīng)用一樣的工作方式。

在使用 ROA 進(jìn)行設(shè)計(jì)時(shí),我們需要把真實(shí)的應(yīng)用需求轉(zhuǎn)化成 ROA 中的資源,基本上遵循以下的步驟:

  • 分析應(yīng)用需求中的數(shù)據(jù)集。
  • 映射數(shù)據(jù)集到 ROA 中的資源。
  • 對(duì)于每一資源,命名它的 URI。
  • 為每一資源設(shè)計(jì)其 Representations。
  • 用 hypermedia links 表述資源間的聯(lián)系。

接下來我們按照以上的步驟來設(shè)計(jì)本文的應(yīng)用案例。

在線用戶管理所涉及的數(shù)據(jù)集就是用戶信息,如果映射到 ROA 資源,主要包括兩類資源:用戶及用戶列表。用戶資源的 URI 用 http://localhost:8182/v1/users/{username} 表示,用戶列表資源的 URI 用 http://localhost:8182/v1/users 表示。它們的 Representation 如下,它們都采用了如清單 1 和清單 2 所示的 XML 表述方式。

清單 1. 用戶列表資源 Representation
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<users>
	<user>
			<name>tester</name>
			<link>http://localhost:8182/v1/users/tester</link>
	</user>
	<user>
			<name>tester1</name>
			<link>http://localhost:8182/v1/users/tester1</link>
	</user>
</users>
清單 2. 用戶資源 Representation
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<user>
	<name>tester</name>
	<title>software engineer</title>
	<company>IBM</company>
	<email>tester@cn.ibm.com</email>
	<description>testing!</description>
</user>

客戶端通過 User List Resource 提供的 LINK 信息 ( 如 : <link>http://localhost:8182/v1/users/tester</link>) 獲得具體的某個(gè) USER Resource。

Restful Web 服務(wù)架構(gòu)

首先給出 Web 服務(wù)使用 REST 風(fēng)格實(shí)現(xiàn)的整體架構(gòu)圖,如下圖所示:

圖 2. REST 實(shí)現(xiàn)架構(gòu)
REST

接下來,我們將基于該架構(gòu),使用 Restlet 給出應(yīng)用的 RESTful Web 服務(wù)實(shí)現(xiàn)。

下面的章節(jié)中,我們將給出 REST Web 服務(wù)實(shí)現(xiàn)的核心代碼片段。關(guān)于完整的代碼清單,讀者可以通過資源列表下載。

客戶端實(shí)現(xiàn)

清單 3 給出的是客戶端的核心實(shí)現(xiàn)部分,其主要由四部分組成:使用 HTTP PUT 增加、修改用戶資源,使用 HTTP GET 得到某一具體用戶資源,使用 HTTP DELETE 刪除用戶資源,使用 HTTP GET 得到用戶列表資源。而這四部分也正對(duì)應(yīng)了圖 2 關(guān)于架構(gòu)描述的四對(duì) HTTP 消息來回。關(guān)于 UserRestHelper 類的完整實(shí)現(xiàn),請(qǐng)讀者參見本文所附的代碼示例。

清單 3. 客戶端實(shí)現(xiàn)
public class UserRestHelper {
//The root URI of our ROA implementation.
public static final tring APPLICATION_URI = "http://localhost:8182/v1";

//Get the URI of user resource by user name. 
private static String getUserUri(String name) {
	return APPLICATION_URI + "/users/" + name;
}

//Get the URI of user list resource.
private static String getUsersUri() {
	return APPLICATION_URI + "/users";
}
//Delete user resource from server by user name.
//使用 HTTP DELETE 方法經(jīng)由 URI 刪除用戶資源
public static void deleteFromServer(String name) {
	Response response = new Client(Protocol.HTTP).delete(getUserUri(name));
	…… 
}
//Put user resource to server.
//使用 HTTP PUT 方法經(jīng)由 URI 增加或者修改用戶資源
public static void putToServer(User user) {
	//Fill FORM using user data.
	Form form = new Form();
 	form.add("user[title]", user.getTitle());
 	form.add("user[company]", user.getCompany());
 	form.add("user[email]", user.getEmail());
 	form.add("user[description]", user.getDescription());
	Response putResponse = new Client(Protocol.HTTP).put(
	getUserUri(user.getName()), form.getWebRepresentation());
 	……
}
//Output user resource to console.
public static void printUser(String name) {
	printUserByURI(getUserUri(name));
}

//Output user list resource to console.
//使用 HTTP GET 方法經(jīng)由 URI 顯示用戶列表資源
public static void printUserList() {
	Response getResponse = new Client(Protocol.HTTP).get(getUsersUri());
	if (getResponse.getStatus().isSuccess()) { 
			DomRepresentation result = getResponse.getEntityAsDom();
 //The following code line will explore this XML document and output
 //each user resource to console.
			……
	} else { 
	 	System.out.println("Unexpected status:"+ getResponse.getStatus()); 
	}
}

//Output user resource to console.
//使用 HTTP GET 方法經(jīng)由 URI 顯示用戶資源
private static void printUserByURI(String uri) { 
	Response getResponse = new Client(Protocol.HTTP).get(uri);
	if (getResponse.getStatus().isSuccess()) { 
 		DomRepresentation result = getResponse.getEntityAsDom();
 		//The following code line will explore this XML document and output
 //current user resource to console.
 ……
 	} else { 
 		System.out.println("unexpected status:"+ getResponse.getStatus()); 
 	}
}
}

服務(wù)器端實(shí)現(xiàn)

清單 4 給出的是服務(wù)器端對(duì)于用戶資源類(UserResourc)的實(shí)現(xiàn),其核心的功能是響應(yīng)有關(guān)用戶資源的 HTTP GET/PUT/DELETE 請(qǐng)求,而這些請(qǐng)求響應(yīng)邏輯正對(duì)應(yīng)了 UserRestHelper 類中關(guān)于用戶資源類的 HTTP 請(qǐng)求。

清單 4. 服務(wù)器端實(shí)現(xiàn)
public class UserResource extends Resource {
private User _user;
private String _userName;
public UserResource(Context context, Request request, Response response) {
//Constructor is here.
……
}
//響應(yīng) HTTP DELETE 請(qǐng)求邏輯
public void delete() {
	// Remove the user from container.
	getContainer().remove(_userName);
 	getResponse().setStatus(Status.SUCCESS_OK);
}

//This method will be called by handleGet.
public Representation getRepresentation(Variant variant) {
 Representation result = null;
 if (variant.getMediaType().equals(MediaType.TEXT_XML)) {	
 	Document doc = createDocument(this._user);
 	result = new DomRepresentation(MediaType.TEXT_XML, doc);
 }
 return result;
}
//響應(yīng) HTTP PUT 請(qǐng)求邏輯。
public void put(Representation entity) {
 if (getUser() == null) {
 //The user doesn't exist, create it
 setUser(new User());
 getUser().setName(this._userName);
 getResponse().setStatus(Status.SUCCESS_CREATED);
 } else {
 	getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
 }
 //Parse the entity as a Web form.
 Form form = new Form(entity);
 getUser().setTitle(form.getFirstValue("user[title]"));
 getUser().setCompany(form.getFirstValue("user[company]"));
 getUser().setEmail(form.getFirstValue("user[email]"));
 getUser().setDescription(form.getFirstValue("user[description]")); 
 //Put the user to the container.
	getApplication().getContainer().put(_userName, getUser()); 
}
//響應(yīng) HTTP GET 請(qǐng)求邏輯。
public void handleGet() {
	super.handleGet();
	if(this._user != null ) {
	    getResponse().setEntity(getRepresentation(
	               new Variant(MediaType.TEXT_XML)));
	    getResponse().setStatus(Status.SUCCESS_OK);	
	} else {
		getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);		
	}
}
//build XML document for user resource.
private Document createDocument(User user) {
 //The following code line will create XML document according to user info. 
	……
}
//The remaining methods here
……
}

UserResource 類是對(duì)用戶資源類的抽象,包括了對(duì)該資源的創(chuàng)建修改(put 方法),讀?。╤andleGet 方法 )和刪除(delete 方法),被創(chuàng)建出來的 UserResource 類實(shí)例被 Restlet 框架所托管,所有操縱資源的方法會(huì)在相應(yīng)的 HTTP 請(qǐng)求到達(dá)后被自動(dòng)回調(diào)。

另外,在服務(wù)端,還需要實(shí)現(xiàn)代表用戶列表資源的資源類 UserListResource,它的實(shí)現(xiàn)與 UserResource 類似,響應(yīng) HTTP GET 請(qǐng)求,讀取當(dāng)前系統(tǒng)內(nèi)的所有用戶信息,形成如清單 1 所示的用戶列表資源 Representation,然后返回該結(jié)果給客戶端。具體的實(shí)現(xiàn)請(qǐng)讀者參見本文所附的代碼示例。

回頁首

使用 SOAP 實(shí)現(xiàn) Web 服務(wù)

本文對(duì)于 SOAP 實(shí)現(xiàn),就不再像 REST 那樣,具體到代碼級(jí)別的實(shí)現(xiàn)。本節(jié)將主要通過 URI,HTTP 和 XML 來宏觀上表述 SOAP Web 服務(wù)實(shí)現(xiàn)的技術(shù)本質(zhì),為下一節(jié) REST Web 服務(wù)與 SOAP Web 服務(wù)的對(duì)比做鋪墊。

SOAP Web 服務(wù)架構(gòu)

同樣,首先給出 SOAP 實(shí)現(xiàn)的整體架構(gòu)圖,如下圖所示:

圖 3. SOAP 實(shí)現(xiàn)架構(gòu)
REST

可以看到,與 REST 架構(gòu)相比,SOAP 架構(gòu)圖明顯不同的是:所有的 SOAP 消息發(fā)送都使用 HTTP POST 方法,并且所有 SOAP 消息的 URI 都是一樣的,這是基于 SOAP 的 Web 服務(wù)的基本實(shí)踐特征。

獲得用戶信息列表

基于 SOAP 的客戶端創(chuàng)建如清單 5 所示的 SOAP XML 文檔,它通過類 RPC 方式來獲得用戶列表信息。

清單 5. getUserList SOAP 消息
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas./soap/envelope/">
	<soap:Body>
		<p:getUserList xmlns:p="http://www."/>
	</soap:Body>
</soap:Envelope>

客戶端將使用 HTTP 的 POST 方法,將上述的 SOAP 消息發(fā)送至 http://localhost:8182/v1/soap/servlet/messagerouter URI,SOAP SERVER 收到該 HTTP POST 請(qǐng)求,通過解碼 SOAP 消息確定需要調(diào)用 getUserList 方法完成該 WEB 服務(wù)調(diào)用,返回如下的響應(yīng):

清單 6. getUserListResponse 消息
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas./soap/envelope/">
	<soap:Body>
			<p:get
				UserListResponse xmlns:p="http://www.">
				<Users>
				<username>tester<username>
				<username>tester1<username>
				......
				</Users>
				<p: getUserListResponse >
	</soap:Body>
</soap:Envelope>

獲得某一具體用戶信息

清單 7. getUserByName SOAP 消息
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas./soap/envelope/">
	<soap:Body>
	 <p:getUserByName xmlns:p="http://www.">
				<username>tester</username>
				</p:getUserByName >
	</soap:Body>
</soap:Envelope>

同樣地,客戶端將使用 HTTP 的 POST 方法,將上述的 SOAP 消息發(fā)送至 http://localhost:8182/v1/soap/servlet/messagerouter URI,SOAP SERVER 處理后返回的 Response 如下:

清單 8. getUserByNameResponse SOAP 消息
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soap:Envelope xmlns:soap="http://schemas./soap/envelope/">
<soap:Body>
	<p:getUserByNameResponse xmlns:p="http://www.">
			<name>tester</name>
			<title>software engineer</title>
			<company>IBM</company>
			<email>tester@cn.ibm.com</email>
			<description>testing!</description>
	</p:getUserByNameResponse>
</soap:Body>
</soap:Envelope>

實(shí)際上,創(chuàng)建新的用戶,過程也比較類似,在這里,就不一一列出,因?yàn)檫@兩個(gè)例子對(duì)于本文在選定的點(diǎn)上對(duì)比 REST 與 SOAP 已經(jīng)足夠了。

回頁首

REST 與 SOAP 比較

本節(jié)從以下幾個(gè)方面來對(duì)比上面兩節(jié)給出 REST 實(shí)現(xiàn)與 SOAP 實(shí)現(xiàn)。

接口抽象

RESTful Web 服務(wù)使用標(biāo)準(zhǔn)的 HTTP 方法 (GET/PUT/POST/DELETE) 來抽象所有 Web 系統(tǒng)的服務(wù)能力,而不同的是,SOAP 應(yīng)用都通過定義自己個(gè)性化的接口方法來抽象 Web 服務(wù),這更像我們經(jīng)常談到的 RPC。例如本例中的 getUserList 與 getUserByName 方法。

RESTful Web 服務(wù)使用標(biāo)準(zhǔn)的 HTTP 方法優(yōu)勢(shì),從大的方面來講:標(biāo)準(zhǔn)化的 HTTP 操作方法,結(jié)合其他的標(biāo)準(zhǔn)化技術(shù),如 URI,HTML,XML 等,將會(huì)極大提高系統(tǒng)與系統(tǒng)之間整合的互操作能力。尤其在 Web 應(yīng)用領(lǐng)域,RESTful Web 服務(wù)所表達(dá)的這種抽象能力更加貼近 Web 本身的工作方式,也更加自然。

同時(shí),使用標(biāo)準(zhǔn) HTTP 方法實(shí)現(xiàn)的 RRESTful Web 服務(wù)也帶來了 HTTP 方法本身的一些優(yōu)勢(shì):

  • 無狀態(tài)性(Stateless)

HTTP 協(xié)議從本質(zhì)上說是一種無狀態(tài)的協(xié)議,客戶端發(fā)出的 HTTP 請(qǐng)求之間可以相互隔離,不存在相互的狀態(tài)依賴?;?HTTP 的 ROA,以非常自然的方式來實(shí)現(xiàn)無狀態(tài)服務(wù)請(qǐng)求處理邏輯。對(duì)于分布式的應(yīng)用而言,任意給定的兩個(gè)服務(wù)請(qǐng)求 Request 1 與 Request 2, 由于它們之間并沒有相互之間的狀態(tài)依賴,就不需要對(duì)它們進(jìn)行相互協(xié)作處理,其結(jié)果是:Request 1 與 Request 2 可以在任何的服務(wù)器上執(zhí)行,這樣的應(yīng)用很容易在服務(wù)器端支持負(fù)載平衡 (load-balance)。

  • 安全操作與冪指相等特性(Safety /Idempotence)

HTTP 的 GET、HEAD 請(qǐng)求本質(zhì)上應(yīng)該是安全的調(diào)用,即:GET、HEAD 調(diào)用不會(huì)有任何的副作用,不會(huì)造成服務(wù)器端狀態(tài)的改變。對(duì)于服務(wù)器來說,客戶端對(duì)某一 URI 做 n 次的 GET、HAED 調(diào)用,其狀態(tài)與沒有做調(diào)用是一樣的,不會(huì)發(fā)生任何的改變。

HTTP 的 PUT、DELTE 調(diào)用,具有冪指相等特性 , 即:客戶端對(duì)某一 URI 做 n 次的 PUT、DELTE 調(diào)用,其效果與做一次的調(diào)用是一樣的。HTTP 的 GET、HEAD 方法也具有冪指相等特性。

HTTP 這些標(biāo)準(zhǔn)方法在原則上保證你的分布式系統(tǒng)具有這些特性,以幫助構(gòu)建更加健壯的分布式系統(tǒng)。

安全控制

為了說明問題,基于上面的在線用戶管理系統(tǒng),我們給定以下場(chǎng)景:

參考一開始我們給出的用例圖,對(duì)于客戶端 Client2,我們只希望它能以只讀的方式訪問 User 和 User List 資源,而 Client1 具有訪問所有資源的所有權(quán)限。

如何做這樣的安全控制?

通行的做法是:所有從客戶端 Client2 發(fā)出的 HTTP 請(qǐng)求都經(jīng)過代理服務(wù)器 (Proxy Server)。代理服務(wù)器制定安全策略:所有經(jīng)過該代理的訪問 User 和 User List 資源的請(qǐng)求只具有讀取權(quán)限,即:允許 GET/HEAD 操作,而像具有寫權(quán)限的 PUT/DELTE 是不被允許的。

如果對(duì)于 REST,我們看看這樣的安全策略是如何部署的。如下圖所示:

圖 4. REST 與代理服務(wù)器 (Proxy Servers)
REST

一般代理服務(wù)器的實(shí)現(xiàn)根據(jù) (URI, HTTP Method) 兩元組來決定 HTTP 請(qǐng)求的安全合法性。

當(dāng)發(fā)現(xiàn)類似于(http://localhost:8182/v1/users/{username},DELETE)這樣的請(qǐng)求時(shí),予以拒絕。

對(duì)于 SOAP,如果我們想借助于既有的代理服務(wù)器進(jìn)行安全控制,會(huì)比較尷尬,如下圖:

圖 5. SOAP 與代理服務(wù)器 (Proxy Servers)
REST

所有的 SOAP 消息經(jīng)過代理服務(wù)器,只能看到(http://localhost:8182/v1/soap/servlet/messagerouter, HTTP POST)這樣的信息,如果代理服務(wù)器想知道當(dāng)前的 HTTP 請(qǐng)求具體做的是什么,必須對(duì) SOAP 的消息體解碼,這樣的話,意味著要求第三方的代理服務(wù)器需要理解當(dāng)前的 SOAP 消息語義,而這種 SOAP 應(yīng)用與代理服務(wù)器之間的緊耦合關(guān)系是不合理的。

關(guān)于緩存

眾所周知,對(duì)于基于網(wǎng)絡(luò)的分布式應(yīng)用,網(wǎng)絡(luò)傳輸是一個(gè)影響應(yīng)用性能的重要因素。如何使用緩存來節(jié)省網(wǎng)絡(luò)傳輸帶來的開銷,這是每一個(gè)構(gòu)建分布式網(wǎng)絡(luò)應(yīng)用的開發(fā)人員必須考慮的問題。

HTTP 協(xié)議帶條件的 HTTP GET 請(qǐng)求 (Conditional GET) 被設(shè)計(jì)用來節(jié)省客戶端與服務(wù)器之間網(wǎng)絡(luò)傳輸帶來的開銷,這也給客戶端實(shí)現(xiàn) Cache 機(jī)制 ( 包括在客戶端與服務(wù)器之間的任何代理 ) 提供了可能。HTTP 協(xié)議通過 HTTP HEADER 域:If-Modified-Since/Last- Modified,If-None-Match/ETag 實(shí)現(xiàn)帶條件的 GET 請(qǐng)求。

REST 的應(yīng)用可以充分地挖掘 HTTP 協(xié)議對(duì)緩存支持的能力。當(dāng)客戶端第一次發(fā)送 HTTP GET 請(qǐng)求給服務(wù)器獲得內(nèi)容后,該內(nèi)容可能被緩存服務(wù)器 (Cache Server) 緩存。當(dāng)下一次客戶端請(qǐng)求同樣的資源時(shí),緩存可以直接給出響應(yīng),而不需要請(qǐng)求遠(yuǎn)程的服務(wù)器獲得。而這一切對(duì)客戶端來說都是透明的。

圖 6. REST 與緩存服務(wù)器 (Cache Server)
REST

而對(duì)于 SOAP,情況又是怎樣的呢?

使用 HTTP 協(xié)議的 SOAP,由于其設(shè)計(jì)原則上并不像 REST 那樣強(qiáng)調(diào)與 Web 的工作方式相一致,所以,基于 SOAP 應(yīng)用很難充分發(fā)揮 HTTP 本身的緩存能力。

圖 7. SOAP 與緩存服務(wù)器 (Cache Server)
REST

兩個(gè)因素決定了基于 SOAP 應(yīng)用的緩存機(jī)制要遠(yuǎn)比 REST 復(fù)雜:

其一、所有經(jīng)過緩存服務(wù)器的 SOAP 消息總是 HTTP POST,緩存服務(wù)器如果不解碼 SOAP 消息體,沒法知道該 HTTP 請(qǐng)求是否是想從服務(wù)器獲得數(shù)據(jù)。

其二、SOAP 消息所使用的 URI 總是指向 SOAP 的服務(wù)器,如本文例子中的 http://localhost:8182/v1/soap/servlet/messagerouter,這并沒有表達(dá)真實(shí)的資源 URI,其結(jié)果是緩存服務(wù)器根本不知道那個(gè)資源正在被請(qǐng)求,更不用談進(jìn)行緩存處理。

關(guān)于連接性

在一個(gè)純的 SOAP 應(yīng)用中,URI 本質(zhì)上除了用來指示 SOAP 服務(wù)器外,本身沒有任何意義。與 REST 的不同的是,無法通過 URI 驅(qū)動(dòng) SOAP 方法調(diào)用。例如在我們的例子中,當(dāng)我們通過

getUserList SOAP 消息獲得所有的用戶列表后,仍然無法通過既有的信息得到某個(gè)具體的用戶信息。唯一的方法只有通過 WSDL 的指示,通過調(diào)用 getUserByName 獲得,getUserList 與 getUserByName 是彼此孤立的。

而對(duì)于 REST,情況是完全不同的:通過 http://localhost:8182/v1/users URI 獲得用戶列表,然后再通過用戶列表中所提供的 LINK 屬性,例如 <link>http://localhost:8182/v1/users/tester</link>獲得 tester 用戶的用戶信息。這樣的工作方式,非常類似于你在瀏覽器的某個(gè)頁面上點(diǎn)擊某個(gè) hyperlink, 瀏覽器幫你自動(dòng)定向到你想訪問的頁面,并不依賴任何第三方的信息。

回頁首

總結(jié)

典型的基于 SOAP 的 Web 服務(wù)以操作為中心,每個(gè)操作接受 XML 文檔作為輸入,提供 XML 文檔作為輸出。在本質(zhì)上講,它們是 RPC 風(fēng)格的。而在遵循 REST 原則的 ROA 應(yīng)用中,服務(wù)是以資源為中心的,對(duì)每個(gè)資源的操作都是標(biāo)準(zhǔn)化的 HTTP 方法。

本文主要集中在以上的幾個(gè)方面,對(duì) SOAP 與 REST 進(jìn)行了對(duì)比,可以看到,基于 REST 構(gòu)建的系統(tǒng)其系統(tǒng)的擴(kuò)展能力要強(qiáng)于 SOAP,這可以體現(xiàn)在它的統(tǒng)一接口抽象、代理服務(wù)器支持、緩存服務(wù)器支持等諸多方面。并且,伴隨著 Web Site as Web Services 演進(jìn)的趨勢(shì),基于 REST 設(shè)計(jì)和實(shí)現(xiàn)的簡(jiǎn)單性和強(qiáng)擴(kuò)展性,有理由相信,REST 將會(huì)成為 Web 服務(wù)的一個(gè)重要架構(gòu)實(shí)踐領(lǐng)域。

回頁首

下載

描述名字大小
本文代碼示例code_rest.zip10 KB

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多