【编程规范】 后端API接口设计编写与文档编写参考
文章目錄
- 0 統(tǒng)一規(guī)范
- 0.1 理清業(yè)務流程
- 0.2 定義前后端開發(fā)的接口規(guī)范
- 0.3 定義接口文檔
- 1 后端接口編寫
- 1.0 后端接口介紹
- 1.0.1 接口交互
- 1.0.2 返回格式
- 1.0.3 CODE狀態(tài)碼
- 1.0.4 Message(Msg)
- 1.0.5 DATA
- 1.1 數(shù)據校驗與異常處理
- 1.1.1 參數(shù)校驗設計
- 1.1.2 全局異常處理
- 1.1.3 自定義異常
- 1.2 數(shù)據統(tǒng)一響應
- 1.2.1 自定義統(tǒng)一響應體
- 1.2.2 響應碼枚舉
- 1.2.3 全局處理響應數(shù)據
- 1.3 其他返回數(shù)據
- 2 接口設計參考
- 2.1 接口設計原則
- 2.1.1 數(shù)據有效性校驗
- 2.1.2 冪等設計
- 2.1.3 數(shù)據加密
- 2.1.4 時間戳機制
- 2.2 設計規(guī)范
- 2.2.1 URL設計
- 2.2.2 返回值設計
- 2.2.3 非RESTful API需求
- 2.2.4 字段命名規(guī)范
- 3 文檔編寫
- 3.1 簡單版本
- 3.1.1 目錄格式
- 3.1.2 案例模板
- 接口說明
- 請求示例
- 請求參數(shù)說明
- 響應示例
- 響應參數(shù)說明
- 3.2 復雜版本
- 3.2.1 目錄格式
- 3.2.2 案例模板
- 封面
- 文檔信息
- 版本歷史
- 目錄
- 文檔具體內容部分
- 編寫目的
- 對接準備事項
- 使用協(xié)議 + 規(guī)范
- 報文規(guī)范
- 加解密規(guī)范
- 業(yè)務接口
- 附錄
- 參考文檔
在一個新型的web應用中,由于中臺只負責數(shù)據的輸送,不涉及具體業(yè)務,所以就需要搭建一個業(yè)務服務來組裝業(yè)務數(shù)據,把 瀏覽器/客戶端 和中臺連接起來。業(yè)務服務將組裝完的數(shù)據以統(tǒng)一的數(shù)據格式返回給客戶端,這里就需要對業(yè)務服務后臺接口進行統(tǒng)一設計。下面就來具體介紹一下如何設計和編寫后端接口。
0 統(tǒng)一規(guī)范
0.1 理清業(yè)務流程
通過需求文檔,描述清楚業(yè)務流程,定義好相關的設計規(guī)范。根據項目大小劃分好前臺和后臺的功能需求,通過需求來得到對應的模塊。
0.2 定義前后端開發(fā)的接口規(guī)范
一般前后端分離項目會擁有不同的數(shù)據格式,例如 json、url等。 這里要通過文檔的形式同前后端一起確定好數(shù)據闡述的格式。
接口地址:不包含接口BASE地址。
請求方式: get、post、put、delete等。
請求參數(shù):數(shù)據格式(默認json)、數(shù)據類型、是否必填、中文描述。
響應參數(shù):類型、中文描述。
0.3 定義接口文檔
這里的接口文檔一般就是對應后臺的實體,即RequestVo(調用后臺接口訪問的實體)和給往前端的ResponseVo(前臺調用接口時前往的實體)。一般來說ResponseVo都會在后臺做一個統(tǒng)一的處理為ResultVo。
對于ResultVo的規(guī)范需要在上一節(jié)中定義好,例如:錯誤碼Code,錯誤描述msg,請求的url,以及實體泛型T。
需要注意的是,這里定義的接口文檔實在徹底了解號數(shù)據流、業(yè)務流的基礎之上完成的。
盡量采用自動化接口文檔,可以做到在線測試,同步更新。 文檔中應包含:接口BASE地址、接口版本、接口模塊分類等。
有了這個接口文檔之后(實質上就是定義實體的過程和對應的json),前后端的開發(fā)基本根據這個文檔去開發(fā)。在實際的項目業(yè)務中,接口文檔會產生版本的迭代,這個時候我們會需要將它放到版本管理器中,不論你用的是git亦或者是svn。
注:除了以上描述的,我們的項目中還有redis,mongoDB,elasticsearch等。這些都是在非常了解業(yè)務的狀況和系統(tǒng)架構下去設計的。后臺運用這些工具去完成接口功能的實現(xiàn)以及系統(tǒng)功能和性能的實現(xiàn)。
1 后端接口編寫
主要是對RESTful接口設計做一個介紹。
1.0 后端接口介紹
1.0.1 接口交互
前端和后端進行交互,前端按照約定請求URL路徑,并傳入相關參數(shù),后端服務器接收
請求,進行業(yè)務處理,返回數(shù)據給前端。
針對URL路徑的restful風格,以及傳入參數(shù)的公共請求頭的要求(如:app_version,api_version,device等),這里就不介紹了,小伙伴們可以自行去了解,也比較簡單。
1.0.2 返回格式
在 0.2小節(jié) 中我們提到了會把ResponseVo 處理為一個統(tǒng)一的ResultVo。
這個ResultVo大致由4個部分組成,分別 是接口請求地址(url)、接口請求方式(get/post)、請求數(shù)據(request)、響應數(shù)據(response)。
在前端的眼中,拿到的數(shù)據就會長這樣,也就是我們所理解的返回格式。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iPfV1rRu-1662523338889)(C:\Users\Hasee\AppData\Roaming\Typora\typora-user-images\image-20220906214352990.png)]
1.0.3 CODE狀態(tài)碼
一般來說沒有明確的規(guī)范要求,具體是看開發(fā)時需要什么就添加什么。
例如,我們要提示前端用戶權限不足,那么我們返回的狀態(tài)碼就可以定義為 403 ;如果我們要告訴前端的數(shù)據參數(shù)異常,我們就可以把返回的狀態(tài)碼定義成 102 。具體的狀態(tài)碼細節(jié)可以參考http請求返回的狀態(tài)碼。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-V9VfIYYH-1662523338892)(C:\Users\Hasee\AppData\Roaming\Typora\typora-user-images\image-20220906215237691.png)]
| 1** | 100~199 | 信息,服務器收到請求,需要請求者繼續(xù)執(zhí)行操作 |
| 2** | 200~299 | 成功,操作被成功接收并處理 |
| 3** | 300~399 | 重定向,需要進一步的操作以完成請求 |
| 4** | 400~499 | 客戶端錯誤,請求包含語法錯誤或無法完成請求 |
| 5** | 500~599 | 服務器錯誤,服務器在處理請求的過程中發(fā)生了錯誤 |
具體可以參考這篇文章:HTTP狀態(tài)碼有哪些分類?
同樣我們可以這么設計:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AMuiZ7de-1662523338893)(C:\Users\Hasee\AppData\Roaming\Typora\typora-user-images\image-20220906215907754.png)]
這樣設計的好處是可以把錯誤類型歸類到某個區(qū)間內,如果區(qū)間不夠,可以設計成4位數(shù)。 這樣前端開發(fā)人員在得到返回值后,根據狀態(tài)碼就可以知道,大概什么錯誤,再根據msg相關的信息描述,可以快速定位。
1.0.4 Message(Msg)
這個字段相對理解比較簡單,就是發(fā)生錯誤時,如何友好的進行提示。一般的設計是和code狀態(tài)碼一起設計。
1.0.5 DATA
返回數(shù)據體,json格式,根據不同的業(yè)務又不同的json體。一般來說返回給前端時會結合msg、code一起返回。
1.1 數(shù)據校驗與異常處理
1.1.1 參數(shù)校驗設計
我們先來看一段數(shù)據校驗的代碼:
public String addUser(User user) {if (user.getId() == null || user.getAccount() == null || user.getPassword() == null ) {return "對象或者對象字段不能為空";}if (StringUtils.isEmpty(user.getAccount()) || StringUtils.isEmpty(user.getPassword())) {return "不能輸入空字符串";}// 參數(shù)校驗完畢后這里就寫上業(yè)務邏輯return "success";}是不是感覺比較熟悉,在最開始不熟悉開發(fā)的時候,都會這么寫過。雖然我們閱讀這段代碼對參數(shù)的校驗是沒有問題的,而且排版也還看得過去。但是每個接口都這么寫顯然會看的比較繁瑣。而且還沒到業(yè)務處理,參數(shù)校驗的代碼就這么多了,顯然會讓人頭大。
在我們引入的依賴 spring-boot-starter-web 中包含了 Validator ,它可以非常方便的定制校驗規(guī)則,并自動完成校驗。只需要在需要校驗的字段加上對應的注解即可,message后面填校驗失敗后的信息。
@NotNull(message = "xxx") @Size(min=*, max=*, message = "xxx") //下面這個注解適用于郵箱驗證 @Email(message="xxx")校驗規(guī)則和錯誤提示信息配置完畢后,接下來只需要在接口中需要校驗的參數(shù)上加上@Valid 注解,并添加BindResult參數(shù)即可方便完成驗證。
BindResult作用:如果有參數(shù)校驗失敗,會將錯誤信息封裝成對象組裝在BindingResult里
當然,每個接口中都添加BindResult顯然會比較繁瑣,我們完全可以把BindResult去掉
例如:
@RestController public class UserController {@Autowiredprivate UserService userService;@RequestMapping("user")public String addUser(@RequestBody @Valid User user,) {return userService.addUser(user);} }1.1.2 全局異常處理
如果我們接口向上一節(jié)那么寫,就會發(fā)現(xiàn)這樣就把所有的問題都響應到前端了,解決這個問題的辦法就是使用全局異常處理。
由于參數(shù)校驗會自動引發(fā)異常,我們就不用再去手動捕捉異常進行處理,這個時候我們就可以用spring boot全局異常處理。
首先,我們需要新建一個ExceptionControllerAdvice類,在這個類上加上**@ControllerAdvice或@RestControllerAdvice注解**,這個類就配置成全局處理類了。(這個根據你的Controller層用的是@Controller還是@RestController來決定)
然后在類中新建方法,在方法上加上**@ExceptionHandler注解**并指定你想處理的異常類型,接著在方法內編寫對該異常的操作邏輯,就完成了對該異常的全局處理。
例如:
@RestControllerAdvice public class ExceptionControllerAdvice {@ExceptionHandler(MethodArgumentNotValidException.class)public String MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {// 從異常對象中拿到ObjectError對象ObjectError objectError = e.getBindingResult().getAllErrors().get(0);// 然后提取錯誤提示信息進行返回return objectError.getDefaultMessage();} }1.1.3 自定義異常
我們在 1.0.1小節(jié) 中了解了返回格式的寫法,我們自定義異常也可以參考這一小節(jié)來編寫。
@Getter //只要getter方法,無需setter public class APIException extends RuntimeException {private int code;private String msg;public APIException() {this(1001, "接口錯誤");}public APIException(String msg) {this(1001, msg);}public APIException(int code, String msg) {super(msg);this.code = code;this.msg = msg;} }當然,我們也需要在全局異常類中添加上我們對自定義異常的處理。
@ExceptionHandler(APIException.class) public String APIExceptionHandler(APIException e) {return e.getMsg(); }這樣就對異常的處理就比較規(guī)范了,當然還可以添加對Exception的處理,這樣無論發(fā)生什么異常我們都能屏蔽掉然后響應數(shù)據給前端,不過建議最后項目上線時這樣做,能夠屏蔽掉錯誤信息暴露給前端,在開發(fā)中為了方便調試還是不要這樣做。
1.2 數(shù)據統(tǒng)一響應
在上一大節(jié)中,我們對全局異常處理和自定義異常已經處理完畢,但是當我們拋出自定義異常的時候,全局異常處理只響應了異常中的錯誤信息msg給前端,并沒有將錯誤代碼code返回。這里就要說到數(shù)據統(tǒng)一響應了。
我們盡管對參數(shù)校驗方式和異常處理方式做好了規(guī)范,但是對響應數(shù)據沒有做好規(guī)范。
1.2.1 自定義統(tǒng)一響應體
統(tǒng)一數(shù)據響應第一步肯定要做的就是我們自己自定義一個響應體類,無論后臺是運行正常還是發(fā)生異常,響應給前端的數(shù)據格式是不變的。
可以參考我們自定義異常類,也來一個響應信息代碼code和響應信息說明msg。
@JsonInclude(JsonInclude.Include.NON_NULL) public class ResultVo<T> {/*** 狀態(tài)碼*/private Integer code;/*** 提示信息,如果有錯誤時,前端可以獲取該字段進行提示*/private String msg;/*** 查詢到的結果數(shù)據,*/private T data;public ResponseResult(Integer code, String msg) {this.code = code;this.msg =msg;} public ResponseResult(Integer code, T data) {this.code = code;this.data = data;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg =msg;}public T getData() {return data;}public void setData(T data) {this.data = data;}public ResultVo(Integer code, String msg, T data) {this.code = code;this.msg =msg;this.data = data;} }然后我們修改全局異常處理的返回值:
@ExceptionHandler(APIException.class) public ResultVO<String> APIExceptionHandler(APIException e) {// 注意哦,這里返回類型是自定義響應體return new ResultVO<>(e.getCode(), "響應失敗", e.getMsg()); }@ExceptionHandler(MethodArgumentNotValidException.class) public ResultVO<String> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {ObjectError objectError = e.getBindingResult().getAllErrors().get(0);// 注意哦,這里返回類型是自定義響應體return new ResultVO<>(1001, "參數(shù)校驗失敗", objectError.getDefaultMessage()); }通過上面的操作,我們將狀態(tài)碼和響應說明還有錯誤提示數(shù)據都返給了前端,并且是所有異常都會返回相同的格式。
這樣無論是正確響應還是發(fā)生異常,響應數(shù)據的格式都是統(tǒng)一的。
數(shù)據格式規(guī)范好了,不過響應碼code和響應信息msg還沒有規(guī)范。所以,必須要將響應碼和響應信息給規(guī)范起來。
1.2.2 響應碼枚舉
要規(guī)范響應體中的響應碼和響應信息我們使用枚舉是最好的。Java中自帶了枚舉類型,我們可以依據枚舉類型創(chuàng)建一個響應碼枚舉類。
@Getter public enum ResultCode {private int code;private String msg;ResultCode(int code, String msg) {this.code = code;this.msg = msg;}//這里的狀態(tài)碼依據項目實際情況自行定義,不必照搬SUCCESS(1000, "操作成功"),FAILED(1001, "響應失敗"),VALIDATE_FAILED(1002, "參數(shù)校驗失敗"),ERROR(5000, "未知錯誤");}我們還要把狀態(tài)碼和信息就會一一對應,這樣比較好維護。
這里要修改響應體的構造方法,讓其只準接受響應碼枚舉來設置響應碼和響應信息。
public ResultVO(T data) {//這里的SUCCESS依據自己定義的ResultCode來替換this(ResultCode.SUCCESS, data); }public ResultVO(ResultCode resultCode, T data) {this.code = resultCode.getCode();this.msg = resultCode.getMsg();this.data = data; }同時我們還應當對全局異常處理的響應碼設置方式進行修改:
@ExceptionHandler(APIException.class) public ResultVO<String> APIExceptionHandler(APIException e) {// 注意哦,這里傳遞的響應碼枚舉return new ResultVO<>(ResultCode.FAILED, e.getMsg()); }@ExceptionHandler(MethodArgumentNotValidException.class) public ResultVO<String> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {ObjectError objectError = e.getBindingResult().getAllErrors().get(0);// 注意哦,這里傳遞的響應碼枚舉return new ResultVO<>(ResultCode.VALIDATE_FAILED, objectError.getDefaultMessage()); }1.2.3 全局處理響應數(shù)據
既然我們對響應數(shù)據做了處理,也對異常做了統(tǒng)一返回響應體,我們可以用一個全局處理來把省略掉用響應體包裝接口返回數(shù)據。
我們同樣是像全局異常處理一樣,定義一個全局處理類 ResponseControllerAdvice 繼承 ResponseBodyAdvice 接口并重寫其中的方法。
// 注意,這里要加上需要掃描的包,即項目的controller包 @RestControllerAdvice(basePackages = {"xxx"}) public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> aClass) {// 如果接口返回的類型本身就是ResultVO那就沒有必要進行額外的操作,返回falsereturn !returnType.getGenericParameterType().equals(ResultVO.class);}@Overridepublic Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {// String類型不能直接包裝,所以要進行些特別的處理if (returnType.getGenericParameterType().equals(String.class)) {ObjectMapper objectMapper = new ObjectMapper();try {// 將數(shù)據包裝在ResultVO里后,再轉換為json字符串響應給前端return objectMapper.writeValueAsString(new ResultVO<>(data));} catch (JsonProcessingException e) {throw new APIException("返回String類型錯誤");}}// 將原本的數(shù)據包裝在ResultVO里return new ResultVO<>(data);} }重寫的這兩個方法是用來在controller將數(shù)據進行返回前進行增強操作,supports方法要返回為true才會執(zhí)行beforeBodyWrite方法,所以如果有些情況不需要進行增強操作可以在supports方法里進行判斷。
對返回數(shù)據進行真正的操作還是在beforeBodyWrite方法中,我們可以直接在該方法里包裝數(shù)據,這樣就不需要每個接口都進行數(shù)據包裝了,省去了很多麻煩。
這樣盡管我們沒有在接口中包裝數(shù)據,但返回給前端的依然是經過包裝后的數(shù)據。
1.3 其他返回數(shù)據
在上一節(jié)中,我們得到了一個統(tǒng)一響應體ResultVo,里面具有code、msg、data。
如果返回給前端的數(shù)據,要求給出分頁信息,那么ResponsePages類中,還需要有Page類,其中至少包括當前頁數(shù),每頁顯示條數(shù)和總條數(shù)信息。分頁使用github的pagehelper工具類來完成。
http返回對象示例: {code: code,msg: msg,pageInfo: { // 分頁信息curPage: 1,pageLimit: 10,page: 1,total: 10}data: {data} }很多時候我們往往需要多種返回數(shù)據,例如添加返回分頁信息,我們可以靈活的根據業(yè)務需求修改ResultVo,但是切記不要在項目進行到中段時再反復修改,一定要在項目開始時就確立,這就是接口開發(fā)文檔存在的意義。
2 接口設計參考
2.1 接口設計原則
參考面向對象原則,接口設計也有六大原則,分別是單一職責原則、里氏替換原則、依賴倒置原則、接口隔離原則、迪米特法則、開閉原則。
接下來介紹一些其他的設計原則。
2.1.1 數(shù)據有效性校驗
常規(guī)性校驗:包括必填字段,長度檢測。格式校驗等。
鑒權校驗:當前請求必須符合權限等。
業(yè)務校驗:根據實際業(yè)務而定,比如訂單金額不能小于0等等。
作用:在接口層做用戶鑒權校驗和參數(shù)校驗,比如做ID基礎校驗,id<0 直接攔截這樣就很有效的能夠解決惡意請求從而導致緩存擊穿的問題。這里有一個小細節(jié),就是我們開發(fā)的時候要保持一個不信任的心,就是不要相信任何的調用方,比如你提供了一個API接口出去,有幾個參數(shù)。我覺得作為被調用方,任何可能的參數(shù)都應該被考慮到去做校驗。因為你不相信任何調用你的人,你不知道她會傳什么參數(shù)給你。舉個簡單的例子,如果你的接口是分頁查詢的,若是你沒有對分頁參數(shù)的大小做限制,調用的人萬一一口氣查詢十萬條數(shù)據,一次請求就會要好幾秒。多幾個并發(fā)不就掛掉了。
2.1.2 冪等設計
冪等的概念: 多次調用對系統(tǒng)的產生的影響是一樣的,即對資源的作用是一樣的,但是返回值允許不同。
HTTP的冪等性:
(1)GET : 只是獲取資源,對資源本身并沒有副作用。天然的冪等性。
(2)HEAD: 本質上和GET一樣,獲取請求頭的信息,主要是探活的作用,具有冪等性。
(3)OPTIONS: 獲取當前URL所支持的方法,因此也是具有冪等性的。
(4)DELETE: 用于資源的刪除,具有副作用,但是他應滿足冪等性,如根據ID刪除某一個資源。調用方法可以調用N次而不用擔心出錯。
(5)PUT: 用于資源更新,有副作用,但是他應該滿足冪等性,如根據ID更新數(shù)據,調用多次和N次的作用是相同的。
(6)POST: 用于資源添加,多次提交可能產生副作用,比如訂單的提交等等。
如何實現(xiàn)冪等(后端的方法):
解決方法為:使用Token。前端向服務端請求一個唯一Token,然后再將Token隨表單一起提交。后端拿到請求的時候需要先將請求的Token去除去做校驗,只有當Token存在的時候才會獲取表單數(shù)據進行DB的操作;若是Token壓根就不存在就說明已經有了其他線程的請求已經在處理了這個數(shù)據,所以這次請求是多余的。
2.1.3 數(shù)據加密
數(shù)據在傳輸?shù)倪^程中我們知道資源數(shù)據都是直接爆露出口來的,用抓包工具就可以很輕松的修改。所以一般我們會對傳輸?shù)臄?shù)據進行加密。常規(guī)的做法是對敏感數(shù)據(比如用戶的身份證號等)做MD5加密。現(xiàn)在主流的做法是使用HTTPS協(xié)議,再HTTP和TCP之間添加一層數(shù)據安全層(SSL層),這一層負責數(shù)據的加密和解密。
2.1.4 時間戳機制
盡管數(shù)據經過了加密處理,但還是會有人一直進行惡意請求,這個時候的簡單做法就是添加時間戳機制,在每次的請求中加入當前時間,服務端對每次請求中的時間(解密之后)與當前系統(tǒng)的時間作對比,看是否在一個固定的時間范圍內,比如5s。惡意偽造的數(shù)據在沒有弄清楚這個混淆時間戳的字段之前,是沒辦法頻繁的更改數(shù)據中心的時間的,超過10s就可以當做非法請求了。
2.2 設計規(guī)范
首先我們要知道,所有的設計考量都應當基于 減少重復工作,增加可讀性可維護性 出發(fā)的。
由于是在設計API接口,我們就應該符合API的一般模式:
ResultType ApiName(ParamType )1. 接口參數(shù),即形參。可以是 string,int,以及其他任意可以稱之為參數(shù)的東西 2. 接口返回值。可以是 string,int,以及其他任意可以稱之為返回值的東西 3. 接口名(簽名)那么在RESTful中我們要對應上這個模式:
HttpResponse URL(HttpRequest)1. HttpRequest:包括請求頭,URL參數(shù),請求body參數(shù) 2. HttpResponse: 包括響應頭,響應的body我們可以總結出一個大概的標準:
1.接口命名必須要做到清晰。 2.接口數(shù)量,越少越好。 3.有明確的輸入輸出總是有返回值,告訴調用端,我到底做了什么,做得怎么樣,即:反饋。2.2.1 URL設計
應該盡量將API部署在專用域名之下: https://api.example.com
①具有統(tǒng)一的前綴或者將其版本化。
版本號分為整型和浮點型 。整型是大功能版本,如v1、v2。浮點型是補充功能版本, 如v1.1、v2.1。
https://api.example.com/v{n} /SERVICE_NAME/v1/users 或者 /APP_NAME/v2/users②url應該盡可能的短小,同一份資源可以由不同的路徑。
③接口的數(shù)量越少越好,能合并的接口就盡量合并。
獲取用戶列表信息:GET /users 獲取單個用戶信息:GET /users/{id}坦白說,獲取一個與獲取一批,似乎并沒有什么語義上的差別, 但是后端的同學就不一樣了,他可能需要寫兩個 View Class。 所以只保留批量的接口,查詢一個時,用 URL 參數(shù)傳遞就行了。2.2.2 返回值設計
參考 1.2 小節(jié)
Response Headers 可以做少量文章,如自定義一個HeaderStatus Code 按照基本規(guī)范來,該404的404,該200的200Response body 基本都是圍繞這個做文章 {是否成功boolean "is_success":錯誤碼是多少number|null "err_code":錯誤信息string|null "err_msg": 錯誤詳情(可選)string|null "err_detail":出錯的時哪個服務string|null "provider": 正常返回時的數(shù)據"response_data": {} }2.2.3 非RESTful API需求
實際業(yè)務開展過程中,可能會出現(xiàn)各種的api不是簡單的restful 規(guī)范能實現(xiàn)的。需要有一些api突破restful規(guī)范原則。特別是移動互聯(lián)網的api設計,更需要有一些特定的api來優(yōu)化數(shù)據請求的交互。
刪除單個or批量刪除: DELETE /v1/product body參數(shù){ids:[]}頁面級API:把當前頁面中需要用到的所有數(shù)據通過一個接口一次性返回全部數(shù)據2.2.4 字段命名規(guī)范
實際上沒有很明確的規(guī)范,但是盡量跟隨數(shù)據庫的風格,即:下劃線風格。 這樣,在 序列化整個 Model 時,也許會很方便。參考阿里巴巴開發(fā)手冊。
3 文檔編寫
在項目開發(fā)中,web項目的前后端分離開發(fā),APP開發(fā),需要由前后端工程師共同定義接口,編寫接口文檔,之后大家都根據這個接口文檔進行開發(fā),到項目結束前都要一直維護。
接口文檔在項目開發(fā)過程中,使前后端工程師有一個統(tǒng)一的文件進行溝通交流開發(fā);項目維護中或者項目人員更迭,方便后期人員查看、維護。
3.1 簡單版本
簡單的核心就是怎么簡單怎么來,怎么省時間怎么來。
如果不知道怎么寫,就把案例寫的越詳細越好。
開發(fā)時間是非常寶貴的,而接口對接通常都是一些工期緊張的情況下去快速編寫,而且面對一些碎片化的時間工作者,一份簡單直觀的文檔可能更受歡迎。
另外,接口文檔最終形式最好是pdf。
3.1.1 目錄格式
? 接口說明 ? 請求示例 ? 請求參數(shù)說明 ? 響應示例 ? 響應參數(shù)說明3.1.2 案例模板
接口說明
接口功能:
本接口用于獲取用戶的token信息。
接口請求地址:
https: xxx/xxx/xxxx 復制代碼請求頭 :
| Authorization | Basic secretKey | 訪問token |
| Content-Type | application/json | 請求方式 |
請求方式:POST
參數(shù)類型:JSON
請求示例
絕大多數(shù)為json,自定義格式
[{"id":"20201219","name":"21.59","age":"ftp_1002"...},{"id":"20201219","name":"21.59","age":"ftp_1002"...}, ] 復制代碼請求參數(shù)說明
| 字段1 | 說明字段1的作用 | varchar(50) | 是 |
| 字段2 | 說明字段2的作用 | int | 是 |
| 字段3 | 說明字段3的作用 | decimal | 是 |
響應示例
成功響應編碼:
{"code: "200","message": "請求成功","data": 返回數(shù)據,格式自定 } 復制代碼失敗響應編碼:
{"code: "200","message": "請求成功","data": 返回數(shù)據,格式自定 } 復制代碼響應參數(shù)說明
| 200 | 成功 |
| 400 | 請求參數(shù)異常 |
| 401 | 授權失敗 |
| 500 | 系統(tǒng)異常 |
3.2 復雜版本
由于不同的公司有不同的文檔格式要求,此處只列舉一個僅供參考的案例。
3.2.1 目錄格式
+ 封面+ 接口文檔名稱+ 接口版本號+ 版權說明 + 文檔信息+ 標題 | 創(chuàng)建時間 | 打印時間 | 文件名 | 存放目錄 | 所有者 | 作用+ 小題:版權聲明 + 版本歷史(重點1)+ \| 版本號 \| 日期 \| 修改者 \| 描述 \|+ \| v1.0.0 \| xxx \| xxx \| xxx | + 目錄+ 結構清晰+ 有條理+ 能快速定位需要的信息(后文會介紹) + 文檔具體內容部分+ 編寫目的+ 對接準備事項+ 測試聯(lián)調+ 上線+ 使用協(xié)議 + 規(guī)范+ 報文規(guī)范+ 請求報文規(guī)范+ 響應報文規(guī)范+ 接口描述+ 報文規(guī)范+ 請求報文+ 響應報文+ 公共報文頭+ 接口碼說明+ 業(yè)務接口+ 查詢接口+ 加解密規(guī)范+ 原則+ 令牌信息+ 加密規(guī)范+ 解密規(guī)范+ 業(yè)務接口+ 具體接口1:+ 說明+ 規(guī)范碼(查表)+ 使用方式+ 請求字段+ 響應字段+ 案例+ 具體接口2............+ 附錄+ 參考資料1+ 參考資料2+ 其他..... 復制代碼3.2.2 案例模板
封面
封面還是比較重要的,畢竟是打開文檔的第一眼內容,下面用阿里的文檔作為參考,可以看到封面一般是如下內容:
公司名稱文檔名稱版本號文檔信息
文檔信息主要記錄這份文件的產生日期以及具體的創(chuàng)建打印日期等。
| 標題 | xxx文檔 |
| 創(chuàng)建日期 | 20xx-xx-xx |
| 打印日期 | 20xx-xx-xx |
| 文件名 | 文檔的全名 |
| 存放目錄 | 文件位置 |
| 所有者 | 某某公司 |
| 作者 | xxx |
版權聲明:(現(xiàn)在這個時代版權是極其重要的)
xxxx所有,不得三方借閱、出讓、出版
版本歷史
版本歷史是很重要的,每次改動都需要有詳細的記錄,這樣才能保證文檔的干凈和有效,同時可以方便review的時候,對于文檔的修訂者進行文檔審查。
| 1.0.0 | 20xx-xx-xx | 創(chuàng)建 | xxx |
| 1.0.1 | 20xx-xx-xx | 修改文檔第一小節(jié)內容 | xxx |
| 1.0.2 | 20xx-xx-xx | 修訂文檔第四小節(jié)的錯誤描述,更新文檔說明 | xxx |
目錄
好的文檔一定有好的目錄,只要按照一定的規(guī)范和格式寫出來的文檔,一般看上去都是十分舒服的。還是用阿里的開發(fā)手冊做參考
文檔具體內容部分
這一部分發(fā)揮的自由空間就比較大了,不同的業(yè)務不同的公司不同的需求不同的人都能寫出萬千種格式的文檔,所以這里也是給一個樣例做參考使用。是否有實用價值因人而異。
為了不讓整個目錄樹太長,這里沒有做標題說明=-=
編寫目的
需要解決什么問題,為什么要這份文檔,這份文檔有什么參考價值?
對接準備事項
接口方可以提供什么內容,接口方需要對接方的那些內容,以及提供的其他信息,比如需要對接方提供 系統(tǒng)應用id,系統(tǒng)唯一標識。向對接方提供密鑰等等
? 1. 測試聯(lián)調:分配測試的密鑰,測試環(huán)境的賬戶和密碼以及其他信息
? 2. 上線:上線之后需要做什么事情,如:替換生產url,替換生產環(huán)境賬戶密碼,替換密鑰為生產密鑰等等
使用協(xié)議 + 規(guī)范
可以是本次對接使用的算法,通信協(xié)議,可以是術語說明或者和業(yè)務相關的其他說明,以及對接的要求都可以,發(fā)揮空間很大,自由設計。
報文規(guī)范
報文規(guī)范是接口對接的核心部分,因為對接大部分的時間基本都是花在接口參數(shù)調試和請求調試等。所以報文規(guī)范算是非常重要的內容。具體內容可以參考簡單版本的接口描述,也可以使用目錄格式進行對應的描述
+ 請求報文:主要為請求的Body,以及請求的header內容,一般都是Json的格式,并且要求UTF8編碼+ 響應報文:返回的格式和內容,也是需要協(xié)商的部分+ 公共報文頭:一般需要重復使用的參數(shù)可以作為公共報文頭,但是不是所有的公共報文頭都是必選,存在可選的參數(shù)+ 接口碼說明:描述接口的注意事項,以及那些字段參數(shù)需要重點關注,主要為提示信息+ 業(yè)務接口:一般表示業(yè)務的返回結果,比如統(tǒng)一2000作為報文的成功響應碼,其他所有碼都是存在對應的接口碼表進行設計。+ 查詢接口:如何才算是表示查詢成功,比如一個還錢的接口當中可能是受理中,拒絕或者處理完成,等查詢接口的信息描述 復制代碼加解密規(guī)范
也是比較重要的部分,也是比較花時間的地方,需要大量調試來打通接口的地方,存在以下的幾個要點。
原則:接口存在一些簡單的原則,比如`非對稱加密`,`數(shù)字簽名`,`時間戳判斷有效性`,具體按照接口的原則自由設置令牌信息:描述令牌是如何生成的,是比較重要的部分,一般由對接雙方溝通完成,最好多以案例和代碼輔助解釋加密規(guī)范:描述接口數(shù)據的加密過程,比較重要的內容信息,最好多以案例和代碼輔助解釋解密規(guī)范:就是解釋接口要如何解密,比如需要拿到服務端給過來的配對公鑰才能解密,再比如使用簽名+參數(shù)進行對照加密驗證簽名是否正確等。加解密規(guī)范參考:
一般的加密方式,一般情況下做到下面這種形式基本可以屏蔽大部分的攻擊:
1. 按照map的key進行字典排序,同時加入`timetamp`值校驗核對時間 2. 把參數(shù)按照一些特殊形式拼接為`key=value&key=value`的形式,末尾帶入時間戳或者其他的一些信息,比如應用Id等核實身份的內容 3. 把這一串按照**AES加密**,然后按照**BASE64編碼**,生成一個編碼串 4. 把BASE64編碼進行**MD5加密**,加密完成之后,得到固定長度的MD5字符串 5. 按照md5串+上面的string在進行一次md5加密,生成簽名,那么這個簽名基本上就唯一的業(yè)務接口
這里基本可以照抄簡單接口模板,因為接口描述每個人的描述不同,下面給出一些基本上涉及的點,另外,到了這一步就盡量用案例輔助,因為案例可以幫助接口閱讀者更快速的上手和理解,注意這一部分的內容:實用性大于理論性。
具體接口:
1. 說明 2. 規(guī)范碼(查表) 3. 使用方式 4. 請求字段 5. 響應字段 6. 案例附錄
可能這部分和說明書一樣基本沒人看,所以不做過多的解釋,附錄不必寫的很詳細的,這里可以隨意施展。
參考文檔
1.CSDN_如何設計和編寫標準的后端接口
2.開源博客_API 接口規(guī)范
3.CSDN_什么是接口文檔,如何寫接口,有什么規(guī)范?
總結
以上是生活随笔為你收集整理的【编程规范】 后端API接口设计编写与文档编写参考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 伦敦交通局设置较低的速度限制
- 下一篇: KB奇遇记(3):信息化沙漠