RESTful是目前比較流行的接口路徑設計規範,基于HTTP,一般使用JSON方式定義,通過不同HttpMethod來定義對應接口的資源動作,如:新增(POST)、删除(DELETE)、更新(PUT、PATCH)、查詢(GET)等。
路徑設計
在RESTful設計規範内,每一個接口被認為是一個資源請求,下面我們針對每一種資源類型來看下API路徑設計。
路徑設計的注意事項如下所示:
- 資源名使用複數
- 資源名使用名詞
- 路徑内不帶特殊字元
- 避免多級URL
新增資源

新增資源使用POST方式來定義接口,新增資源資料通過RequestBody方式進行傳遞,如下所示:
curl -X POST -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users -d '{ "name": "恒宇少年", "age": 25, "address": "山東濟南"}'
新增資源後接口應該傳回該資源的唯一辨別,比如:主鍵值。
{ "id" : 1, "name" : "恒宇少年"}
通過傳回的唯一辨別來操作該資源的其他資料接口。
删除資源
删除資源使用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方式進行傳遞删除條件的資料清單,上面示例中通過資源的主鍵值集合作為删除條件,當然也可以通過資源的其他元素作為删除的條件,比如:name
更新資源
在更新資源資料時使用PUT方式比較多,也是比較常見的,如下所示:
curl -X PUT -H 'Content-Type: application/json' https://api.yuqiyu.com/v1/users/1 -d '{ "name": "恒宇少年", "age": 25, "address": "山東濟南"}'
查詢單個資源
- 唯一辨別查詢單個資源
curl https://api.yuqiyu.com/v1/users/1
通過唯一辨別查詢資源時,使用路徑方式傳遞辨別值,展現出層級關系。
- 非唯一辨別查詢單個資源
curl https://api.yuqiyu.com/v1/users?name=恒宇少年
查詢資源資料時不僅僅都是通過唯一辨別值作為查詢條件,也可能會使用資源對象内的某一個元素作為查詢條件。
分頁查詢資源
分頁查詢資源時,我們一般需要傳遞兩個參數作為分頁的條件,page代表了目前分頁的頁碼,size則代表了每頁查詢的資源數量。
curl https://api.yuqiyu.com/v1/users?page=1&size=20
如果分頁時需要傳遞查詢條件,可以繼續追加請求參數。
https://api.yuqiyu.com/v1/users?page=1&size=20&name=恒宇少年
動作資源
有時我們需要有動作性的修改某一個資源的元素内容,比如:重置密碼。
使用者的唯一辨別在請求路徑中進行傳遞,而修改後的密碼通過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。
狀态碼
針對不同的狀态碼我們要做出不同的回報,下面我們先來看一個常見的參數異常錯誤響應設計方式:
# 發起請求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 恒宇少年 - 于起宇 */@Datapublic class ApiResponse implements Serializable { private T data; private String code; private String errorMsg; private Long timestamp;}
- data
由于每一個API的響應資料類型不一緻,是以在上面采用的泛型的泛型進行傳回,data可以傳回任意類型的資料。
- code
業務邏輯異常碼,比如:USER_NOT_FOUND(使用者不存在)這是接口的約定
- errorMsg
對應code值得描述。
- timestamp
請求響應的時間戳
總結
RESTful是API的設計規範,并不是所有的接口都應該遵循這一套規範來設計,不過我們在設計初期更應該規範性,這樣我們在後期閱讀代碼時根據路徑以及請求方式就可以了解接口的主要完成的工作。