RESTful規範Api最佳設計實踐

RESTful是目前比較流行的接口路徑設計規範,基於HTTP,通常使用JSON方式定義,經過不一樣HttpMethod來定義對應接口的資源動做,如:新增(POST)、刪除(DELETE)、更新(PUT、PATCH)、查詢(GET)等。json

路徑設計

RESTful設計規範內,每個接口被認爲是一個資源請求,下面咱們針對每一種資源類型來看下API路徑設計。api

路徑設計注意事項以下所示:app

  • 資源名使用複數
  • 資源名使用名詞
  • 路徑內不帶特殊字符
  • 避免多級URL

新增資源

請求方式 示例路徑
POST
https://api.yuqiyu.com/v1/users

新增資源使用POST方式來定義接口,新增資源數據經過RequestBody方式進行傳遞,以下所示:curl

curl -X POST -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users -d '{
    "name": "恆宇少年", 
    "age": 25, 
    "address": "山東濟南"
}'複製代碼

新增資源後接口應該返回該資源的惟一標識,好比:主鍵值。url

{
  "id" : 1,
  "name" : "恆宇少年"
}複製代碼

經過返回的惟一標識來操做該資源的其餘數據接口。spa

刪除資源

請求方式 示例路徑
備註
DELETE
https://api.yuqiyu.com/v1/users
批量刪除資源
DELETE
https://api.yuqiyu.com/v1/users/{id} 刪除單個資源

刪除資源使用DELETE方式來定義接口。設計

  • 根據主鍵值刪除單個資源
curl -X DELETE https://api.yuqiyu.com/v1/users/1複製代碼

將資源的主鍵值經過路徑的方式傳遞給接口。代理

  • 刪除多個資源
curl -X DELETE -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users -d '{
      "userIds": [
          1, 
          2, 
          3
      ]
  }'複製代碼

刪除多個資源時經過RequestBody方式進行傳遞刪除條件的數據列表,上面示例中經過資源的主鍵值集合做爲刪除條件,固然也能夠經過資源的其餘元素做爲刪除的條件,好比:namecode

更新資源

請求方式 示例路徑
備註
PUT
https://api.yuqiyu.com/v1/users/{id} 更新單個資源的所有元素
PATCH
https://api.yuqiyu.com/v1/users/{id} 更新單個資源的部分元素

在更新資源數據時使用PUT方式比較多,也是比較常見的,以下所示:orm

curl -X PUT -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users/1 -d '{
    "name": "恆宇少年", 
    "age": 25, 
    "address": "山東濟南"
}'複製代碼

查詢單個資源

請求方式 示例路徑
備註
GET
https://api.yuqiyu.com/v1/users/{id}
查詢單個資源
GET
https://api.yuqiyu.com/v1/users?name={name} 非惟一標識查詢資源

  • 惟一標識查詢單個資源
curl https://api.yuqiyu.com/v1/users/1複製代碼

經過惟一標識查詢資源時,使用路徑方式傳遞標識值,體現出層級關係。

  • 非惟一標識查詢單個資源
curl https://api.yuqiyu.com/v1/users?name=恆宇少年複製代碼

查詢資源數據時不只僅都是經過惟一標識值做爲查詢條件,也可能會使用資源對象內的某一個元素做爲查詢條件。

分頁查詢資源

請求方式 示例路徑
GET
https://api.yuqiyu.com/v1/users?page=1&size=20

分頁查詢資源時,咱們通常須要傳遞兩個參數做爲分頁的條件,page表明了當前分頁的頁碼,size則表明了每頁查詢的資源數量。

curl https://api.yuqiyu.com/v1/users?page=1&size=20複製代碼

若是分頁時須要傳遞查詢條件,能夠繼續追加請求參數。

https://api.yuqiyu.com/v1/users?page=1&size=20&name=恆宇少年複製代碼

動做資源

有時咱們須要有動做性的修改某一個資源的元素內容,好比:重置密碼。

請求方式 示例路徑
備註
POST
https://api.yuqiyu.com/v1/users/{id}/actions/forget-password -

用戶的惟一標識在請求路徑中進行傳遞,而修改後的密碼經過RequestBody方式進行傳遞,以下所示:

curl -X POST -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users/1/actions/forget-password -d '{
    "newPassword": "123456"
}'複製代碼

版本號

版本號是用於區分Api接口的新老標準,比較流行的分別是接口路徑頭信息這兩種方式傳遞。

  • 接口路徑方式

咱們在部署接口時約定不一樣版本的請求使用HTTP代理轉發到對應版本的接口網關,經常使用的請求轉發代理好比使用:Nginx等。

這種方式存在一個弊端,若是多個版本同時將請求轉發到同一個網關時,會致使具體版本的請求轉發失敗,咱們訪問v1時可能會轉發到v2,這並非咱們指望的結果,固然能夠在網關添加一層攔截器,經過提取路徑上班的版本號來進行控制轉發。

# v1版本的請求
  curl https://api.yuqiyu.com/v1/users/1
  # v2版本的請求
  curl https://api.yuqiyu.com/v2/users/1複製代碼

  • 頭信息方式

咱們能夠將訪問的接口版本經過HttpHeader的方式進行傳遞,在網關根據提取到的頭信息進行控制轉發到對應版本的服務,這種方式資源路徑的展示形式不會由於版本的不一樣而變化

# v1版本的請求
  curl -H 'Accept-Version:v1' https://api.yuqiyu.com/users/1
  # v2版本的請求
  curl -H 'Access-Version: v2' https://api.yuqiyu.com/users/1複製代碼

這兩個版本的請求可能請求參數、返回值都不同,可是請求的路徑是同樣的。

版本頭信息的Key能夠根據自身狀況進行定義,推薦使用Accpet形式,詳見Versioning REST Services

狀態碼

RESTful設計規範內咱們須要充分的裏面HttpStatus請求的狀態碼來判斷一個請求發送狀態,本次請求是否有效,常見的HttpStatus狀態碼以下所示:

狀態碼 發生場景
200
請求成功
201
新資源建立成功
204
沒有任何內容返回
400
傳遞的參數格式不正確
401
沒有權限訪問
403
資源受保護
404
訪問的路徑不正確
405
訪問方式不正確,GET請求使用POST方式訪問
410
地址已經被轉移,不可用
415
要求接口返回的格式不正確,好比:客戶端須要JSON格式,接口返回的是XML
429
客戶端請求次數超過限額
500
訪問的接口出現系統異常
503
服務不可用,服務通常處於維護狀態。

針對不一樣的狀態碼咱們要作出不一樣的反饋,下面咱們先來看一個常見的參數異常錯誤響應設計方式:

# 發起請求
curl -X POST -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users -d '{
    "name": "", 
    "age": 25, 
    "address": "山東濟南"
}'
# 響應狀態
HttpStatus 200
# 響應內容
{
    "code": "400", 
    "message": "用戶名必填."
}複製代碼

在服務端咱們能夠控制不一樣狀態碼、不一樣異常的固定返回格式,不該該將全部的異常請求都返回200,而後對應返回錯誤,正確的方式:

# 發起請求
curl -X POST -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users -d '{
    "name": "", 
    "age": 25, 
    "address": "山東濟南"
}'
# 響應狀態
HttpStatus 400
# 響應內容
{
    "error": "Bad Request", 
    "message": "用戶名必填."
}複製代碼

響應格式

接口的響應格式應該統一

每個請求成功的接口返回值外層格式應該統一,在服務端能夠採用實體方式進行泛型返回。

以下所示:

/**
 * Api統一響應實體
 * {@link #data } 每一個不一樣的接口響應的數據內容
 * {@link #code } 業務異常響應狀態碼
 * {@link #errorMsg} 業務異常消息內容
 * {@link #timestamp} 接口響應的時間戳
 *
 * @author 恆宇少年 - 於起宇
 */
@Data
public class ApiResponse<T> implements Serializable {
    private T data;
    private String code;
    private String errorMsg;
    private Long timestamp;
}複製代碼

  • data

因爲每個API的響應數據類型不一致,因此在上面採用的泛型的泛型進行返回,data能夠返回任意類型的數據。

  • code

業務邏輯異常碼,好比:USERNOTFOUND(用戶不存在)這是接口的約定

  • errorMsg

對應code值得描述。

  • timestamp

請求響應的時間戳


總結

RESTfulAPI的設計規範,並非全部的接口都應該遵循這一套規範來設計,不過咱們在設計初期更應該規範性,這樣咱們在後期閱讀代碼時根據路徑以及請求方式就能夠了解接口的主要完成的工做。

相關文章
相關標籤/搜索