Retrofit解析1之前哨站——理解RESTful

從今天開始,我開始學習Retrofit,整體Retrofit內容如下:

好的,那開始今天的內容

隨著Google對HttpClient的摒棄,和Volley的逐漸沒落,OkHttp開始異軍突起,Retrofit對OkHttp進行了強制依賴。Retrofit是由Square公司出品的針對于Android和Java的類型安全的Http客戶端,如果看源碼會發現其實本質上是OkHttp的封裝,使用面向接口的方式進行網絡請求,利用動態生成的代理類封裝了網絡接口請求的底層,其將請求返回JavaBean,對網絡認證REST API進行了很友好的支持。使用Retrofit將會極大的提高我們應用的網絡體驗。

本篇文章是Retrofit的前哨站——理解RESTful。因為retrofit是基于RESTful架構。所以在講解Retrofit之前,先來復習一下RESTful。本篇文章內容如下:

  • 1.RESTful的前世今生
  • 2.RESTful的理解
  • 3.RESTful的原則
  • 4.RESTful、RPC、SOAP的愛恨情仇
  • 5.總結

在移動互聯網的大潮下,前后端分離的場景下,隨著docker等技術的興起,“微服務”的概念越來越被大家接受的的情況下,RESTful API成為越來越重要的移動端和服務器的交互形式。尤其在很多互聯公司或者傳統公司轉型擁抱互聯網的公司,一套設計良好的RESTful API能夠幫助互聯網產品支持單個服務端+多個客戶端的場景。RESTful架構本身是一個風格而不是一個標準,本文將圍繞RESTful架構展開討論,歡迎大家拍磚。

RESTful架構,就是目前最流行的一種互聯網軟件架構。它結構清晰、符合標準、易于理解、方便擴展,所以得到越來越多的應用。
但是,RESTful到底是什么?并不是一個容易說清楚的問題。那么我們先來了解下RESTful的前世今生。

一、RESTful的前世今生

、RESTful之父---Roy Fielding

在介紹RESTful之前需要介紹一下Roy Fielding。RESTful這個單詞因為是在2000年的他的博士論文中首次出現的。
Roy Fielding是一個非常重要的人,他是HTTP協議(1.0/1.1)的主要設計者、Apache服務器軟件的作者之一,Apache基金會的第一任主席。所以他的這篇論文已經發布,就引起了關注,并且立即對互聯網產生了深遠的影響。

Roy Fielding.png

他這樣介紹論文的寫作目的:

"本文研究計算機科學兩大前沿----軟件和網絡----的交叉點。長期以來,軟件研究主要關注軟件設計的分類、設計方法的演化,很少客觀地評估不同的設計選擇對系統行為的影響。而相反地,網絡研究主要關注系統之間通信行為的細節、如何改進特定通信機制的表現,常常忽視了一個事實,那就是改變應用程序的互動風格比改變互動協議,對整體表現有更大的影響。我這篇文章的寫作目的,就是想在符合架構原理的前提下,理解和評估以網絡為基礎的應用軟件的架構設計,得到一個功能強、性能好、適宜通信的架構。"
(This dissertation explores a junction on the frontiers of two research disciplines in computer science: software and networking. Software research has long been concerned with the categorization of software designs and the development of design methodologies, but has rarely been able to objectively evaluate the impact of various design choices on system behavior. Networking research, in contrast, is focused on the details of generic communication behavior between systems and improving the performance of particular communication techniques, often ignoring the fact that changing the interaction style of an application can have more impact on performance than the communication protocols used for that interaction. My work is motivated by the desire to understand and evaluate the architectural design of network-based application software through principled use of architectural constraints, thereby obtaining the functional, performance, and social properties desired of an architecture. )

二、REST的理解

(1)、Roy Fielding將他對互聯網軟件的架構原則,定名為REST,即Representation State Transger的縮寫。所以REST指的是一組架構約束條件與原則。"如果一個架構符合REST的約束和原則",我們就稱它為RESTful架構。
(2)、Representation State Transger有人翻譯為表征狀態轉移,也有人翻譯為表述性狀態轉移,也有人翻譯為表現層狀態轉移,也有人翻譯為"呈現狀態轉移"。我的理解是"表征狀態轉移"。
(3)、REST本身并沒有創建新的技術、組件或服務,而隱藏在RESTful背后的理念就是使用Web的現有特征和能力,更好地使用現有Web標準中的一些準則和約束。雖然REST本身收Web技術的影響很深,但是理論上REST架構風格并不是綁定在HTTP上,只不過目前HTTP的唯一與REST相關的實例。所以我們這里描述的REST也是通過HTTP實現的REST。

三、相關概念的梳理:

  • REST(Respresentational State Transfer):定義了一套基于Web的數據交互方式的設計風格
  • RESTful:符合REST風格的API就可以叫做RESTful API。注意,本文講到的RESTful API設計方法將是基于HTTP和JSON實現方式,但不論HTTP還是JSON都不是REST的標準。REST只是風格,沒有標準。
  • RPC(動詞) :REST強調資源,RPC強調動作,所以REST里面的URI是名詞,RPC多為動詞短語,然而它們也并不是完全不想管的兩個東西。
  • WebService:一個貌似很久遠的概念,有一套它的理論,基于Web的服務提供者

四、REST關鍵原則

由于REST定義了應該如何正確的使用Web標準,例如HTTP和URI。如果你在設計應用程序的時能堅持REST原則,那就預示著你將會得到了一個優質的Web架構。REST有5條關鍵原則如下:

  • 1.為所有“事物”定義ID
  • 2.將所有事物鏈接在一起
  • 3.使用標準方法
  • 4.資源多重表述
  • 5無狀態通信

下面讓我們來詳細解析一下:

1、為所有"事物"

這里我使用了"事物"來代替更準確的術語"資源"。大家可以想一下人們構建的系統,通常會找到一系列的值來標識關鍵的抽象,就像數據庫中的"表"里面的"主鍵"一樣,那么在web的世界里面是什么那?大家答對了,就是URI,RUI構成了一個全局命名的空間。使用URI來標識你的關鍵資源意味著它們獲得了一個全局的、唯一的ID。

記得之前看過一本書叫<Dont make me think>,里面闡述了一種思想,就是盡量使用那些能夠被絕大多數人所能理解的規則,這樣你做的任何東西對別人來說是沒有學習成本的。同樣的道理,如果在你的application里面定義一個對默寫事務的抽象,別人能瞬間理解(比如消費者,應該定義為consumer)。更加直觀的講,在淘寶上每一個商品都有他的一個固定的ID(URI)。否則,那就扎心了,老鐵。

當這樣設計的時候,很多人會懷疑這樣是否會直接向外面暴露你的數據庫記錄。但是其實它和隱藏現實細節之間沒有任何沖突,通常值得被URI標識的事物——資源——要比數據庫記錄要抽象的多。例如,一個訂單資源可以由訂單項,地址以及其他方面組成。標識所有值的標識事物,領會這一個觀念可以引導你創建出在傳統應用程序中不常見的資源。一個流程,一個談判,一次飯局,這都是應該標識的事務的示例。

下面是一些你可能想到的URI的例子:

http://example.com/customers/1234
http://example.com/orders/2007/10/776654
http://example.com/products/4554
http://example.com/processes/salary-increase-234

基于我創建了便于閱讀的URI——這個有用的觀點,盡管不是RESTful設計所必須的,但是你們應該會十分容易的推測出 URI的含義:他們明顯的"標識"某一數據的數據項。
繼續往下看

http://example.com/orders/2007/11
http://example.com/products?color=green
大家看到這兩個URI看起來和之前有些不同,因為它們不是對一件事物的標識,而是對一類事物的標識(假設第一個URI標識了所有2007年11月份的訂單,第二個標識了綠色產品的集合)。但是這些集合自己也是事物(資源),也應該被標識。

PS:使用全局、唯一的命名規則的好處,既適用于瀏覽器中的Web應用,也適用于當前的移動互聯網中的app應用。

最后總結一下:使用URI標識所有值得標識的事務,特別是應用中提供的所有"高級"資源,無論這些資源代表單一數據、數據項集合、虛擬亦或實際的對象還是計算結果等。

2、將所有事務連接在一起

這里說的是“鏈接”的思想,鏈接在我們HTTP中是非常常見的概念。但是他的用處應該不止于此,比如下面的json

{"url":"https://www.hao123.com/"}

但你看見上面的鏈接,應用程序可以通過檢索json,跟蹤鏈接獲取更多的信息。使用URI表示鏈接的優雅之處在于,鏈接可以指向不同應用、不同服務器甚至位于南極洲的服務器。因為URI命名規范是全球標準,構成WEB的所有資源都可以互聯互通。

鏈接的原則還有一個更重要的方面——應用"狀態"。簡而言之,實際上服務器端為客戶端提供一組鏈接,使客戶端能通過連接將應用從一個狀態改變為另一個狀態。稍后我們會在另一篇文章探究這個方面的影響;目前,只需要記住鏈接是構成動態應用的有效方式。

總結一下:任何可能的情況下,使用鏈接指引可以被標示的資源。也正是鏈接造就了現在的Web。

3、使用標準方法

當你在瀏覽器里面輸入一個uri的時候,瀏覽器就會跳轉你制定的地址。但是你的瀏覽器是怎么知道該如何操作的那?那是因為瀏覽器知道所有的資源(uri)都支持同樣的接口。一套同樣的方法,如下圖所示


方法.png

其中HEAD,TRACE,OPTIONS,CONNECT 在RESTful API 設計中不常用,這些Methods具體定義可以在

其中 HEAD,TRACE,OPTIONS,CONNECT 在 RESTful API 設計中不常用,這些 Methods 具體定義可以在這里找到。如果需要,可以根據相關語意來實現具有對應功能的API。

如果你采用RESTful的方式暴露應用功能,那這條原則和它同樣也適用于你。

為什么使用標準方法如此重要?從根本上說,它使你的應用稱為Web的一部分——應用程序為Web變成Internet上最成功的應用所做的貢獻,與它添加到Web中的資源數量成比例。采用RESTful方式,一個應用可能會向Web中添加數以百萬計的客戶uri。

統一接口也使用所有理解HTTP應用協議的組件能與你的應用交互。通用客戶程序就(generic client)是從從收益的例子,比代理,緩存,網關等。

總結一下:為了使客戶端程序能與你的資源相互協作,資源應該正確地實現默認的HTTP協議(HTTP),也就是使用標準的GET/PUT/POST/DELETE方法。

4、資源多重表述

到目前為止我們忽略了一個復雜的問題:客戶端程序如何知道怎么處理檢索的導數據,比如GET或者POST請求的結果?其實HTTP采取的方式是允許數據處理和操作調用之間的關系分離的。換句話說,如果客戶程序知道如何處理一種特定的數據格式,那就可以與所有提供這種格式的資源交互。讓我們再用一個例子來闡述這個觀點,利用HTTP內容協商(content negotiation),客戶端程序可以請求一種特定格式的表述:

GET /customers/1234 HTTP/1.1
Host: example.com 
Accept: application/vnd.mycompany.customer+xml  

響應的返回值可能是一些公司專有的XML格式表述的客戶信息。
假設客戶端發起的請求是另外一個不同的請求,如下:

GET /customers/1234 HTTP/1.1
Host: example.com 
Accept: text/json

響應的返回值就可能是json格式的
這說明為什么理想的情況下,資源表述應該采用標準格式,如果客戶端對HTTP應用協議和數據格式都有所"了解"。那么它就可以用一種有意義的方式與世界上任意一個RESTful HTTP應用交互。
在實際應用中,資源多重表述還有其他的好處:如果你為你的資源提供HTML和XML兩種表述方式,那這些資源不僅可以被你的應用所用,還可以被任意標準Web瀏覽器所用。你的應用信息可以被所有會使用Web的人獲取到。
總結:針對不同的需求提供資源多重表述。

五、無狀態通信

所謂無狀態通信,即所有的資源,都可以通過URI定位,而且這個定位與其他資源無關,也不會因為其他資源的變化而改變。有狀態和無狀態的區別,舉個例子說明下。例如查詢某員工的工資,以為查詢工資是需要登錄系統,進入查詢工資的頁面,執行相關操作后,獲取工資的信息,則這種情況吸是有狀態的,因為查詢征信的每一步操作都依賴于前一步的操作,只要前置操作不成功,后續操作就無法執行;如果輸入一個URI即可得到指定某人的工資,則這種情況是無狀態的,因為獲取工資的信息是不依賴其他資源或者狀態,且這種情況下,某人的工資信息是一個資源,由一個URI與之相對應,可以通過HTTP中的GET方法獲取資源,這就是典型的RESTful風格。

有狀態.png
無狀態.png

五、ROS、SOA、REST與RPC

ROA即Resource Oriented Architecture,RESTful架構風格的服務是圍繞資源展開的,是典型的ROA架構,雖然ROA與SOA并不沖突,甚至把ROA看做SOA的一種未嘗不可。因此RESful架構風格的服務通常被稱之為ROA架構,很少提及SOA架構,以便更加顯示的與RPC區分。

PRC風格曾是WebService的主流,最初是基于XML-PRC協議,后來漸漸被SOAP協議取代;但是RPC的風格不僅僅可以用HTTP,還可以用TCP或者其他通信協議。但是PRC風格的服務,受服務器采用語言的束縛比較大。進入移動互聯網時代后,RPC風格的服務很難在移動端使用,而RESTful風格的服務,由于可以直接以json為載體承載數據,以HTTP方法為統一接口完成數據操作,客戶端的開發部依賴于服務實現的技術,移動端也可以輕松使用服務,這也加劇了REST取代RPC稱為Web Service的主導

RPC與RESTful的區別如下面兩個圖所示

RPC.png
RESTful.png

六、總結

最后我們從REST的名字來重新分析并總結一下REST。
REST的全拼是(Respresentational State Transfer) 其中Respresentational指的是資源即Resource 而State Transfer 是狀態轉化,那么我從這兩個方面來重新解讀一下

1、資源(Resources)是REST的核心

REST開發又被稱作“面向資源的開發”,這說明對于資源的抽象是設計RESTful API的核心內容。RESTful API建模的過程與面向對象建模類似,是以名詞為核心的。這些名詞就是資源,任何可命名的抽象概念都可以定義為一個資源。對于業務的抽象是設計一套好的RESTful API的基礎,這就好比建房子打地基,如果地基沒有打好,后面建的樓就很容易歪掉,其美觀度,可維護性,可擴展性就會大大折扣。我會建議在設計初期一定要在資源的定義上多花功夫,抽象出適合業務發展的資源。也就是說一開始要把產品的RESTful風格定義下來,后面的擴展都可以基于這樣的風格延續下去。

下面是幾條小的建議:

  • 理清資源的層次結構,比如業務針對的范圍是養雞場,那么學校會是一級資源(/school),老師(/school/teachers),學生(school/students)就是二級資源。
  • 資源盡量用準備的英文名詞去表達,資源組都是用復數來表示。一個號的資源定義一定是不需要解釋的。
2、資源的狀態轉化(State Transfer)

訪問一個網站或者接口,就代表客戶端和服務器一次交互的過程,而這個過程勢必會涉及到數據和狀態的變化。而HTTP協議又是無狀態的,這就意味著所有的狀態都保存在服務器。如果某個客戶端想要做操作服務器必須通過某種手段讓服務器發生狀態轉換,那么客戶端就可以操作資源,而資源的狀態轉化就轉化為對資源的各種操縱。而這些操作通常是通過HTTP協議的四種方法來實現的GET/POST/PUT/DELETE。還有其他不常用的方法PATCH/HEAD/OPTIONS。

最后再次重申RESTful 是風格,不是標準。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,185評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,446評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,951評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,189評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,718評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,800評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,420評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,755評論 2 371

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,604評論 25 707
  • 一說到REST,我想大家的第一反應就是“啊,就是那種前后臺通信方式。”但是在要求詳細講述它所提出的各個約束,以及如...
    時待吾閱讀 3,443評論 0 19
  • REST本身是一個高度抽象化的架構風格,因而總是很難對它有一個比較深入且印象深刻的理解。寫這篇文章的目的,是自己對...
    vito1994閱讀 2,873評論 0 26
  • 五十雙期盼的目光,緊緊的盯著你,你婉然一笑,捉不到緊張的影子,你的一言一語、一個音調、一聲輕笑,都深深刻在我心間,...
    歐飛云閱讀 360評論 0 0