當技術leader說要把接口設計成RESTful,我拒絕了

一、前言

最近準備重寫公司一箇舊項目,每次想起這個項目,內心總忍不住要吐槽一波,難受。具體細節就不說了,水平不一樣,見仁見智,也不是本文的重點。就是此時,技術leader說要把接口設計成RESTful規範,我拒絕了,這東西適合當前業務開發嗎?先後端對接麻煩嗎?前端

這東西之前上學時就據說過,但工做也沒看見有人徹底以此設計web

我也想遵照這傳說中的規範,可現實不容許啊json

二、RESTful

REST(Representational State Transfer),直譯爲表現層資源轉換,具體就不說了hhh,相關文章一大堆,但REST感受沒有一個十分明確的標準,更趨向於一種接口設計風格,按照基本的約束條件進行開發設計。後端

三、基本接口命名

有人說RESTful API能夠一會兒讓別人知道這個url是幹什麼的,但說到底不就是取決於咱們的接口命名嗎?接口作到見名知義,用良好的英文命名,不也能達到效果。因此,參考業界部分規範,我定義了以下命名。api

3.1 獲取數據

拿通用的訂單模塊舉例,最基礎無非是兩種場景-獲取列表 or 獲取詳情數據結構

  1. 獲取列表 /api/order/orderList
  2. 獲取詳情 /api/order/orderInfo

前面不加get?架構

  1. 以前我也加,時間久了總以爲礙眼hhh,這裏定義get,service層又定義一個相同或差很少的方法名,總以爲在 重複命名
  2. 爲了讓接口路徑更短更精簡,乾脆省略get,後面就約定以 list/info結尾就認爲是獲取數據信息了。

不學RESTful在數據實體後加s表示複數?app

  1. 對於後端 數據結構而言,List更合適
  2. 有些前端須要作列表展現,List翻譯後更 見名知義
  3. 以s結尾的單詞需加es就不說了,有些單詞是單複數同行,若是加s我會以爲這人英文語法不行啊,不加又像單數。因此爲了統一,List最好

3.2 複雜業務場景

有時咱們的核心業務需求不定,相同的實體信息在不一樣場景須要提供不一樣的數據,其實到咱們後端就是根據不一樣過濾條件查詢出實體信息,有些所謂的RESTful規範說是在url後加參數信息,如:編輯器

/orders?state=finish&userId=123url

這也是我不喜歡RESTful的緣由之一,某些場景下,過濾信息是固定不變的,不能經過前端傳參決定,並且url後帶參數的傳參也有弊端。

回到不一樣場景不一樣命名,最好能從產品用戶角度出發,好比:

  1. 查看我全部訂單 /api/order/myAllOrderLIst
  2. 獲取已完成的訂單 /api/order/finishiedOrderLIst
  3. 獲取可開票的訂單 /api/order/invoiceOrderList

3.3 增/改/刪/其餘非獲取動做

  • addXXX - 增長
  • saveXXX -保存
  • updateXXX -修改更新
  • deleteXXX -刪除
  • pushXXX -推送
  • payXXX -支付
  • ........

若是作後臺管理系統這種項目,確實能夠用list、info、save、update、delete一把梭了。每一個數據實體一定要有這些方法

3.4 myBatis-plus中良好的命名

myBatis-plus封裝好了一些service、mapper方法,增刪改查都有十分規範的命名。並且在相同的操做都有適合本身的命名。

動做 service mapper(dao)
save insert
remove delete
update update
get/list select

3.5 不一樣版本的相同接口

有些接口須要兼容不一樣的APP版本,若是增長字段不能知足,無可奈何需增長新的請求路徑,可加個v一、v2版本前綴,原接口名不變,加個版本前綴還能夠看到接口的歷史修改,方便維護。

  • /api/order/v1/orderInfo
  • /api/order/v2/orderInfo

四、統一ApiRequest

4.1 Spring還自然支持RESTful規範

除了場景的GET、POST請求註解,Spring還有@PutMapping 、@PatchMapping、 @DeleteMapping 註解,標識不一樣的請求方式。

不只如此,SpringMVC還支持參數綁定。

@RequestMapping(value = "/orders/{id}", method = RequestMethod.GET)
public void getById(HttpServletRequest request, @PathVariable("id") Long id){
    System.out.println(id);
}
複製代碼

這....又給咱們提供一種獲取參數的形式..............

4.2 自定義ApiRequest

既然拒絕了RESTful,那咱們規定,前端統一用json形式POST請求接口傳遞參數,後端攔截器拿到請求,自定義ApiRequst類,將請求信息(請求頭/請求體)統一封裝,這樣先後端架構都保持統一,更有利於聯調。

@Data
public class ApiRequest implements Serializable {
    private String appVersion;      //請求頭-app版本號
    private Integer deviceType;     //請求頭-設備類型
    private String deviceName;      //請求頭-設備類型
    private String secret;
    private String token;
    private Map data;           //請求體-業務參數
}
複製代碼

Controller層統一形式接收

/**
 * TestApi
 * @param apiRequest
 * @return
 */
@PostMapping(value = "/testList")
public ApiResponse testList(ApiRequest apiRequest) {
  Long id = apiRequest.getDataParamAsLong("id", 0L);
  String name = apiRequest.getDataParamAsString("name", "");
  return ApiReponse.ok();
}
複製代碼

五、寫在最後

其實我不並反對RESTful,僅僅想說出本身的想法。存在即合理嘛。我也曾經嘗試過其規範,真是一把辛酸淚。我以爲只有適合本身的業務,能提升開發效率、先後端溝通效率的,就是良好的規範,規範並無一個十分統一的參考

咦,好像還漏了接口返回結果Response沒說吧,這在RESTful裏貌似也有說起。

相關文章
相關標籤/搜索