RESTful這種架構已經具有很長的時間和歷程了,但似乎最近restful這個詞出現的頻率特別高,目前不是很清楚是因為我自個兒現在是以restful風格寫程式產生的孕婦效應,還是單頁面程式開發的流行造成的。
其實一開始我也是不想寫這篇文章的,因為網路上與restful相關的文章挺多,而且都寫得挺好的,都具有比較高的參考價值。但是我仔細梳理了我所看過的文章,發現大家基本上講的是restful的理論經驗,好像並沒有過多的提及restful實際程式設計上的一些經驗總結。而且關於這方面的經驗總結我曾經也想找找來做參考也並沒有找到,因此,我寫這篇文章,希望一些人能得到一些參考(因為是我個人實踐,可能有些不符合大流的地方,那就請多多包涵或者指出來了)。
另外這篇文章我不會去講一些底層restful支援怎麼設計(restful框架怎麼設計),要說這個的話,那麼內容太長了,我主要講應用層面的東西,也就是具體業務邏輯的一些東西,當然會做一些基本的引申講解。
資源
說到restful就不得不說資源這個東西了,restful的每一個介面所對應的應該是一個資源。那麼,在restful裡面,“資源”這個詞其實應該算是一個抽象概念了,這個“資源”所包含的資源就不僅僅是常規意義上的資源了。我覺得換一種方式叫法,把這種資源叫做物件,可能會更加方便理解。
當然,首先我們其實應該說一下什麼是資源。資源包含的東西很多,從圖片到音訊、視訊等資料,以及文字等都是資源。也就是說,伺服器上存在的資料就是資源。
但是,單獨說資源沒有太多意義,應該說資源的表現方式才有意義,或者說資料的表現方式才有意義,此處挺重要的,這個涉及到後續我說的restful風格設計方面的東西。通常來說,我們開啟一個URL所能看到的就是一個完整的html介面,而其實,這個html介面就是資源,html所顯示出來的圖片、音訊、視訊等等都是資源。說到這裡可能有些人在做開發過程中對於一些東西具有誤解,認為restful風格所獲取的資源是服務端返回json
資料。關於這個,我們應該搞清楚幾個概念:
- 資料型別:就是服務端返回的資料型別,如html、圖片、視訊、Excel表格、world文件等等;
- 傳輸方式:非同步和同步;
- 序列和並行傳輸: 序列傳輸是等一個資料傳輸完成再傳輸另外一個資料,並行是同時執行。
這三個東西我就不展開細說了,說起來比較複雜,我就說一下序列和並行與非同步和同步的一個大致講解就好了,很多人覺得非同步是並行執行的,或者說把非同步理解成並行執行的,這其實不一定,非同步只能說執行的時候在某個流程執行的時候可以開始其他任務執行,減少阻塞。
請求方式
常用的請求方式大致就是:GET
、POST
、PUT
、DELETE
、OPTIONS
。
GET:介面從字面意識理解,就是獲取資料的,而我們在設計的時候,GET應該是包含兩種資料獲取方式,一種是獲取整體資料列表,一種是根據指定ID獲取資料。
POST:是新增資料用的,此請求方式設計的介面是新增資料;
PUT:是修改資料介面,如果要對資源做資料修改,那麼程式應該考慮放在這個介面中;
DELETE:很容易理解,這個請求方式對應的是對介面的刪除操作;
OPTIONS:這個介面蠻有意思的,通常這個介面設計為返回當前介面的一些資訊,比如有哪些欄位,哪些欄位允許請求哪些欄位不允許等。
那麼後端的業務邏輯程式應該向外提供基本的五個介面,如:
interface Api {
public function index() {} // GET 列表介面 /api
public function view() {} // GET 單個資料介面 /api/:id
public function create() {} // POST 建立介面 /api
public function update() {} // PUT 修改介面 /api/:id
public function delete() {} // DELETE 刪除介面 /api/:id
}複製程式碼
業務邏輯設計思維方向
嗯,說了以上一大堆,那麼這個點估計才是比較關鍵的東西。
可以看以上的那段程式碼介面,我後面的註釋做了請求方式和功能性說明,來看一下update
這個介面,這個介面需要注意的是,通常設計的修改介面後面必須要帶上指定的資料id,這裡的:id
指的是資源id引數。從這裡來看,似乎對於資源的修改具有一定的侷限性,當然刪除也如此。然後,我想很多人應該就開始有一個疑問了:“臥槽,老子要做批量修改,咋辦?這restful也太侷限了吧?”。
對,我開始就是這麼想的,後來經過我的思考,我發現並不是這樣。我上文提到,服務端任何資料都是資源,而且資源在restful裡應該算是一個抽象的意義。上文沒法做說明,但其實,這個是關乎到程式設計上的一些問題的。
首先,我們來假設有這樣一個例子,我們要批量刪除一堆商品資料。按照傳統的思維,使用者批量選擇,然後把這一堆id傳遞到後端,然後後端根據這一批id來進行刪除。我說這個,並不是要表達在restful裡這套思維行不通,首先應該肯定這是對的,但是,我們要做的是跳出這期間設計到的另外一個思維。也就是此時我們把商品當做一個資源操作,此時,我們應該把“刪除商品”當做一個資源,而不是商品。那麼我們在設計介面的時候,就具有非常大的意義了。我們把“刪除商品”當做一個資源,暫且把這個介面定義為:/delete-goods
。那麼,刪除就是對應的post介面,也就是建立“刪除商品”,那麼撤銷刪除可以對應delete介面,也就是刪除“刪除商品”。
以上描述得可能有些拗口,但實際上就是這樣,如果這麼設計,我們遵循了restful的標準,其實互動流程與傳統沒有太多差別,唯一的差別就是思想的轉換。分析以上,其實我們應該得出一些結論:
做restful設計的時候,程式設計思維應該要做一定的轉換,在不同的場景思考到底什麼才應該是資源,應該把什麼當做資源?
做restful應該把邏輯拆分得更清晰,沒個邏輯物件只做五件事情:看列表資料、看單個資料、增加資料、修改資料、刪除資料。
以上我雖然是就刪除來說的,其實批量修改等也貼合這種思想,也包括我之前回答的一個問題,就是批量閱讀訊息這種操作也貼合於這種思想。
其他
restful互動一般會遵循一些資料結構協議或者HTTP狀態值,比如不同的操作結果對應不同的HTTP狀態值,且出錯會返回指定的錯誤資訊方便前端進行提示等。
當然restful介面的設計為了完全遵循自然語義也可以採用請求資源列表採用複數請求方式(語言中的單數詞和複數詞)等等。
不管怎麼變化,我覺得最基本的還是不同的請求方式對應的不同操作問題,所有的操作對應的還是同一個介面。
以上就是我的一些應用場景的理解和總結,歡迎大家一起交流。