基於.NetCore開發部落格專案 StarBlog - (21) 開始開發RESTFul介面

程式設計實驗室發表於2022-12-17

前言

最近電腦壞了,開源專案的進度也受到一些影響

這篇醞釀很久了,作為本系列第二部分(API介面開發)的第一篇,得想一個好的開頭,想著想著就鴿了好久,索性不扯那麼多了,直接開寫吧~

關於RESTFul

網上很多相關的文章都要把RESTFul歷史來龍去脈給複製一遍,所以我這就不重複了,現在主要的HTTP介面風格就倆:RPC和RESTFul。

舉個例子就可以看出這倆的區別

RPC風格

分別是增刪改查的介面

操作 HTTP方法 URL
post /blog/add
post /blog/deleteById
post /blog/updateById
get /blog/getAll

可以看出RPC風格的特點:

  • 基本就是用post和get這倆方法來操作介面
  • URL的命名跟函式命名一樣,都是動詞,一目瞭然

PS:RPC這種幾乎一個團隊一個風格,我見過有人把所有介面都做成post方法,然後請求引數全部用json格式放在body裡的。

關鍵是這個請求引數還不統一,同個專案不同開發人員寫的請求引數格式不一致,很噁心。(微信有些介面也是這樣)

RESTFul風格

分別是增刪改查的介面

操作 HTTP方法 URL
post /blog/
delete /blog/{id}/
put /blog/{id}/
get /blog/
get /blog/{id}/

可以看出RESTFul風格的特點:

  • 利用各種HTTP方法來實現增刪改查(其實還有patch、head這些方法,不展開了)
  • URL的命名是名詞,以資源名稱作為URL,更統一
  • 使用get獲取資源,方便後端、客戶端、閘道器這些地方做快取,提高效能

介面返回值

除了請求介面,RESTFul還建議介面返回的時候根據不同狀態使用不同的HTTP狀態碼。

以下是HTTP定義的五類狀態碼。

類別 描述
1xx:資訊 通訊傳輸協議級資訊。
2xx:成功 表示客戶端的請求已成功接受。
3xx:重定向 表示客戶端必須執行一些其他操作才能完成其請求。
4xx:客戶端錯誤 此類錯誤狀態程式碼指向客戶端。
5xx:伺服器錯誤 伺服器負責這些錯誤狀態程式碼。
  • 比如新增了資料,返回 201 (created)
  • 新增、更新、刪除這些不需要返回資料的介面,返回 204 (no content)
  • 沒登入,返回 401 (unauthorized)
  • 找不到,返回 404 (not found)
  • 沒許可權,返回 403 (forbidden)

這樣就很清晰了,看介面返回的狀態碼就能知道結果如何。

在一些前端ajax庫(比如axios)中,返回碼如果是4xx或5xx,就會丟擲異常,這樣訪問邏輯就可以根據錯誤做出一些提示。

例子

假設介面返回結構是這樣

{
    "successful": true,
    "message": "請求成功",
    "data": [{...}, {...}, {...}]
}

請求介面的 JavaScript 程式碼如下

axios.get('/blog/')
	.then(res => msg.success(`請求成功,返回資訊:${res.data.message}`))
	.catch(res => msg.error(`請求失敗,返回資訊:${res.data.message}`))

但是!實際場景很複雜,HTTP標準狀態碼就40個,根本不夠用啊。

所以這些HTTP狀態碼只能對返回值做個大概的分類,複雜系統還是得自己定義一套錯誤碼。

小結

這倆各有優劣,RESTFul看起來比較統一優雅,但表達能力有限;RPC的URL命名看起來比較隨意,不過自由發揮的空間也很大。

我個人是比較傾向RESTFul風格的,所以StarBlog使用了RESTFul風格的介面,不過這並不能滿足全部功能需求,所以參考Django的RestFramework,將RESTFul和RPC稍微結合一下。

舉個例子:要在部落格增刪改查的基礎上增加設定置頂、點贊等功能。

操作 HTTP方法 URL
設定置頂 post /blog/{id}/setTop/
點贊 post /blog/{id}/thumbUp/
獲取置頂文章 get /blog/getTop/

可以看到這種縫合怪是以RESTFul為基礎,增刪改查以外的功能,在對應的資源上使用RPC風格。

setTop / thumbUp / getTop 這些動詞在RestFramework裡面也叫 action ,意為對一系列資源執行的動作。

關於HTTP方法,對資源有修改的,使用post方法,沒有修改單純讀取的,使用get方法。

介面開發規劃

本系列文章更新順序跟StarBlog部落格開發的順序基本一致,即在已有MVC架構網站的基礎上,增加RESTFul介面,用於管理後臺(前後端分離)對部落格進行配置管理。

目前我把介面分成這幾類

  • auth - 認證授權,顧名思義,後面會細說
  • admin - 管理員相關,主要功能有配置管理、訪問記錄、系統監控等
  • blog - 部落格相關,功能就是文章、分類、圖片等資訊的crud
  • common - 公用介面,StarBlog除了部落格功能外,還以介面形式提供了一些小功能,如一句詩、一言、隨機圖片、主題切換等
  • test - 測試介面,用於一些功能測試,在正式環境會關閉訪問
  • links - 友情連結管理,這個功能比較複雜,單獨做成一個分類

後續會有更多類似友情連結這樣比較複雜的功能加入(比如評論),這種會單獨做成一個分類。

PS:之前在開發部落格前臺的時候,把大部分功能都寫在了 services 裡面,現在開發介面的時候就派上用場了,很多邏輯都是通用的,在介面的controller裡面只需要呼叫這些 services 就可以了。

需要關注的其他東西

本文不涉及具體實現,只是作為RESTFul介面開發部分的前言或者大綱,介面開發看似就crud四個操作很簡單,實際上比想象的複雜。

例如,獲取文章列表介面,部落格的文章數量會很多,不可能一個介面返回所有文章資訊,因此要做分頁處理,同時我們還希望能在文章列表實現關鍵詞過濾、分類、狀態篩選、排序等功能;

已登入使用者才能發表評論,管理員才能管理文章,因此需要實現認證授權、角色管理等功能;

同一時間可能有很多人訪問部落格(或者是爬蟲),需要對介面做限流處理,以免程式崩潰;

介面數量多起來了,swagger顯示太雜亂,需要對介面分組,或者更換swagger前端;

正式環境不想讓使用者看到swagger介面文件,可以隱藏或者給swagger加鎖;

頻繁訪問的資源,可以使用服務端快取提升效能,減輕IO壓力,使用客戶端快取降低伺服器流量;

耗時操作(如批次匯出文章、傳送簡訊通知)放到非同步任務佇列(或者後臺任務)裡執行;

以上列舉的種種只是我在撰寫本文的當下考慮部落格需要用到的,實際上應該還有很多。只能說後端的水很深,開發本專案的過程也是一個不斷探索、實踐的過程,“No silver bullet”,沒有任何技術能適用全部場景,只能在不斷的積累中得出某個場景下的最佳實踐。

OK,本文就到這吧。

系列文章

相關文章