REST與RESTFul API最佳實踐


我經常會面試一些做PHP的開發者,讓我很奇怪的是,10個人總有8個多不知道什么是REST服務,甚至是沒有聽說過。但RESTFul API已經是現在互聯網里對外開放接口的主流模式,可參考:

豆瓣API https://developers.douban.com/wiki/?title=api_v2

GitHub https://developer.github.com/v3/

數一數年限,據我接觸REST到現在也差不多有8年左右了。可能大家現在對從JavaScript客戶端直接訪問服務器API這種模式非常的習以為常,但在8年前,Web並不是現在這個樣子的。要說REST,我們先來看看在REST流行之前Web客戶端是如何訪問服務器接口的。

早期在移動端沒有流行之前,Web API的概念還非常的弱,當時是網站盛行的年代,基本遵循着后台-前端的模型。后台產生數據,然后通過“模板”的形式將數據綁定到前端HTML代碼里(渲染)。如下圖所示:

圖片描述

那么這里就有一個“域”的概念,JavaScript只能訪問同一個域的服務器。比如我們將一個站點部署在A這個域名www.a.com下,那么這個站點的前端JavaScript只能訪問域名為www.a.com的服務端。如果我們需要訪問非A站點的其他“服務”怎么辦?看看下圖:

圖片描述

在當時通用的做法是使用SOAP,Simple Object Access Protocol,簡單對象協議,它使用XML作為數據的描述。我們看看使用SOAP的解決方案:

圖片描述

JavaScript是不能直接訪問SOAP服務的,需要首先訪問自己的網站后台,再有網站后台訪問SOAP服務。而且不同語言的網站后台,方位SOAP服務都需要有首先生成自己特定語言的“代理類”,Java有Java的、C#有C#的,這相當的繁瑣與不好理解。這個時候我們的思考點來了,網站的后台對我來說意義是什么? 我為什么不能直接訪問服務?為什么我不能把網站里的業務代碼也提取成服務,最后變成以下的理想情況:

圖片描述

網站的后台幾乎是個“殼子”,只負責網站本身的HTML頁面、CSS、JavaScript文件等靜態頁面。而業務邏輯,交給服務來提供就好了。這樣做的最大的好處是,業務變得獨立了,可以被多個“網站”來共享訪問了。有沒有覺得挺熟悉?這個模式就是現在VUE、AngularJS等框架做的單頁面應用程序。但是,在當時這種模式並不流行。我在很多年前就嘗試這樣的思維來構建Web,但是由於沒有現在VUE、AngularJS等強大的SPA框架支持,效果並不好。但,我相信這種簡潔的模式是Web的未來。我一向崇尚簡潔,當年丟掉Flex、Silverlight、ASP.Net WebForm,獨獨選擇JavaScript就是因為其他幾個封裝太多。

很多人認為模板引擎就是很好的前后端分離,可我不這么認為,SPA才是真正的前后端分離,他們之間使用AJax通信,前端就是最簡單的HTML,前端開發人員一行服務器代碼都看不到,這才是真的和語言無關,才是真正的前后端分離。

我來分析下,為什么以前SPA應用並不流行。
第一,一個是網站的思維根深蒂固;
第二,就是出於性能考慮,單頁面頻繁的Ajax請求將給服務器造成巨大的壓力。而網站網頁的靜態化技術已經是非常的成熟的了,所以SPA這個概念在早期並不怎么提倡。而且SPA也有自己的局限性,並不是所有的網站都適合用SPA來代替。但現在服務器緩存技術的發展(特別是Memcache和Redis出現后)大大的解決了服務器支持SPA負載過高的問題,甚至比傳統的網頁靜態化技術更加的簡單易用;再加上VUE、AngularJS強大的能力,這才使SPA真正的流行起來。
第三,前端要跨域訪問服務器在當時並不是那么容易,沒有一個標准的規范來定義跨域,各種旁門左道的跨域都不是那么的好用。

那么我個人認為有兩個標致性的事物刷新了人們對於API和服務的理解:一個是移動端的流行,第二個就是REST理念的流行。
移動端我們就不談了。我們來談談REST。我個人認為REST並不是什么技術,而是由於它的流行,讓人們逐漸的接受了服務即資源,擴展和打破了開發者對Web的理解。

沒有REST的時候,客戶端可不可以直接跨域訪問服務?可以。但並沒有一個標准來引導開發者如何設計出適合服務的API接口。REST的流行,替代了SOAP(某些領域里SOAP還是有一席之地),它足夠簡單、輕量、語義明確,非常適合移動端盛行的這個年代。

REST:REpresentational State Transfer,中譯為“表屬性狀態傳遞”。這是什么鬼?這並不重要,本來就個名字就源自於國外的一個博士的一篇論文。我們主要要知道基於這篇論文里的理論,衍生出了RESTFul API的接口設計風格。
我們一起來看看RESTFul API有哪些特點:

  1. 基於“資源”,數據也好、服務也好,在RESTFul設計里一切都是資源。
  2. 無狀態。一次調用一般就會返回結果,不存在類似於“打開連接-訪問數據-關閉連接”這種依賴於上一次調用的情況。
  3. URL中通常不出現動詞,只有名詞
  4. URL語義清晰、明確
  5. 使用HTTP的GET、POST、DELETE、PUT來表示對於資源的增刪改查
  6. 使用JSON不使用XML

    我舉個例子:
    網站:/get_user?id=3
    RESTFul: GET /user/3 (GET是HTTP類型)

有些同學可能會說,GET、POST我也經常用啊。但是在網站里的GET和POST同RESTFul中的GET、POST是不一樣的。網站里使用GET、POST的選擇點在於,簡單的用GET、復雜對象用POST;但在REST里,GET對應的是查詢一個資源,而POST對應的是新增一個資源,意義是決然不同的。理解這一點非常重要。

好,我們接着來看一看RESTFul API的一些最佳實踐原則:

  1. 使用HTTP動詞表示增刪改查資源, GET:查詢,POST:新增,PUT:更新,DELETE:刪除
  2. 返回結果必須使用JSON
  3. HTTP狀態碼,在REST中都有特定的意義:200,201,202,204,400,401,403,500。比如401表示用戶身份認證失敗,403表示你驗證身份通過了,但這個資源你不能操作。
  4. 如果出現錯誤,返回一個錯誤碼。比如我通常是這么定義的:

圖片描述

  1. API必須有版本的概念,v1,v2,v3
  2. 使用Token令牌來做用戶身份的校驗與權限分級,而不是Cookie。
  3. url中大小寫不敏感,不要出現大寫字母
  4. 使用 - 而不是使用 _ 做URL路徑中字符串連接。
  5. 有一份漂亮的文檔~(很重要)

以上只是列出了RESTFul的部分實踐原則,並非全部。 給出一個典型的RESTFul API設計風格:

https://api.z.cn/v1/product/recent?page=3&size=20

以上URL非常容易理解,分頁獲取最新若干的Product資源。

最后,我們想聊一下,RESTFul API到底好用嗎?某些情況好用,某些情況非常不好用。什么情況好用,什么情況不好用呢?
我的一個經驗性的總結:對於開放的API,豆瓣、新浪微博、GitHub,好用,非常合適;對於內部開發,不好用。
基於資源型的RESTFul API 接口粒度和返回結果過於的“粗”,它通常返回的都是完整的數據模型,這對於客戶端非常不友好。但開放API之所以開放,就是因為它不知道你到底需要什么返回結果,既然不知道,那么我干脆都返回給你。這樣的好處是通用,但客戶端不好處理。你只需要一個字段,服務器啪的丟給你十幾個,作為客戶端開發者你怎么想?

內部開發由於需求非常明確,通常來說服務器是不應該簡單粗暴的直接甩資源實體給客戶端的。那RESTFul API就不能接入到內部開發嗎?當然不是,我們需要靈活一些借鑒RESTFul中的優點,來設計我們的內部API。那么如何簡化,這就不是一篇文章能夠說清楚的了,也沒有一個統一的標准,需要自己去琢磨和體會。

最后舉個例子吧,我個人在開發內部接口時會保留絕大多數的REST 特性,但我不會嚴格的只寫增、刪、改、查四個接口。必要的時候,還是要靈活處理一下。而且錯誤碼、狀態碼這些非常優秀的特性,必須保留。

好了,關於RESTFul我們就介紹到這里。特別強調,接口設計是一個非常依賴於經驗和重構的技術活兒,設計接口需要有一些藝術家的天賦(真實體會),你看GitHub的接口就非常的“美”。不要覺得很簡單,真的比寫代碼還難。難道大家不覺得,有時候起名字真的是一件很難的事兒嘛?

本文原創發布於慕課網 ,轉載請注明出處,謝謝合作!


作者: 7七月 
鏈接:http://www.imooc.com/article/17650
來源:慕課網
本文原創發布於慕課網 ,轉載請注明出處,謝謝合作!

 

出處:https://blog.csdn.net/u013063153/article/details/72811976


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM