java架構篇之請求參數格式的規範化(架構師入門 初學)

注意:我現在所講的內容針對於rest風格的接口服務(請求值和返回值數據都爲json)

首先聲明一下架構觀點:

規範性的公共類:必須封裝,必須使用

便利性的公共類:謹慎封裝,可用可不用

在講述完此節內容後,會對以上觀點進一步說明,相信有更深的感悟


參數規範化

首先說明下在開發中遇到的一些問題,在查詢分頁參數的時候,可能會看到這樣的兩份代碼

張三寫的代碼:

  /**
   * 分頁查詢用戶列表
   * @param pageIndex 頁碼
   * @param pageSize 每頁顯示數量
   * @return 分頁後的數據(示例用)
   */
  public List<Data> queryPagedUserList(Integer pageIndex,Integer pageSize){
    //查詢結果並返回
  }

李四寫的代碼:

 /**
   * 分頁查詢消息列表
   * @param currentPage 頁碼
   * @param count 每頁顯示數量
   * @return 分頁後的數據(示例用)
   */
  public List<Data> getMessageList(Integer currentPage,Integer count){
    //查詢結果並返回
  }

仔細對照一下,發現相同的參數含義,兩個人寫出不完全不同的參數名。

張三: 頁碼 pageIndex 分頁大小pageSize

李四: 頁碼 currentPage 分頁大小count

前端在調用這兩個接口的時候,需要根據不同接口選擇不同的參數名,如果不在這方面規範一下,會對前端造成很多困擾,不同的頁面用不同參數名字,即使他們的含義一樣。

怎麼解決這種由於不同人開發造成的命名不規範的問題呢

現在有很多項目,以書面的方式,開會說明參數的命名規範。當後面有新人加入項目後,可能由於講解不到位,又會出現自己命名的情況(我就遇到過這種情況)

下面講的這種方式,叫強制規範化,也就是說你只能這樣命名。

首先分析下前端提交的參數類型:

(1)接口私有查詢參數:和接口業務相關的參數,比如查詢用戶列表有用戶名,查詢消息列表有消息日期

(2)數據列表參數:這種參數一般是用來批量保存數據的,比如說你想批量新增員工,這個參數就是一個list類型的數據

(3)接口私有查詢參數 + 分頁排序參數:這種參數在後臺管理系統用的非常多,規定數據表格按照什麼字段排序,怎麼進行分頁,以什麼條件進行查詢

以上面參數分析爲參照,我們有了這樣一種類圖


下面解釋我大量應用了泛型,對泛型不明白的小夥伴要補補泛型的知識了

BaseRequest定義

public class BaseRequest implements Serializable{
}

可以看到裏面內容是空的,只是實現了Serializable接口,這個接口本身是個空接口,僅僅表明這個類可以通過序列化在網絡上傳輸,在某些框架上必須要求傳輸的Bean實現Serializable接口。

另外:通過讓所有參數繼承BaseRequest的方式,可以全局添加請求參數

(1)第一種參數類型(只包含接口私有參數)

@Data
public class Request<T extends Serializable> extends BaseRequest{
    
    private T param;
}

注:@Data是Lombok註解,lombok主要用來給bean自動生成set/get方法。lombok的詳盡用法請參照資料

可以看到,我定義了一個泛型,並繼承了BaseRequest,到這裏你可能不太明白,這個到底怎麼用,下面給出使用示例

  public List<Data> getMessageList(@RequestBody Request<String> request){
    String param = request.getParam();
    //查詢結果並返回
  }

前端對應的參數爲


注:@RequestBody作用是將前臺傳過來的json轉爲Bean,前提是框架配置好

這裏可以看到我放了一個String類型的參數進去了,表明這個接口接受的參數類型是String,當前端傳遞了一個帶param字段的json對象過來後,後臺轉換成Bean,賦值到Request的param字段上。


當需要傳遞多個參數的時候怎麼辦呢,這時候我們就需要一個bean了,比如這樣

@Data
public class ClientLoginParam implements Serializable{
  private String username;
  private String password;
}

然後接口定義這麼寫

  public List<Data> getMessageList(@RequestBody RestRequest<ClientLoginParam> request){
  ClientLoginParam = request.getParam();
}

前端對應的參數


當然,接口私有參數可以定義一個全局的BaseParam參數

public class BaseParam implements Serializable{

}
public class ClientLoginParam extends BaseParam //後面省略

(2)第二種參數類型:數據列表參數

@Data
public class ListRequest<T extends Serializable> extends BaseRequest{
    private List<T> params;
}

本質上和是Request用法是一樣的,只不過param類型變成了List<T>,用法上這麼用

  public List<Data> getMessageList(@RequestBody ListRequest<ClientLoginParam> request){
    List<ClientLoginParam> param = request.getParams();
    //查詢結果並返回
  }

(3)接口私有查詢參數 + 分頁排序參數(這個是重點)

@Data
public class PageRequest<T extends Serializable> extends BaseRequest{
    //分頁參數
    private PageParam pageParam;
    //排序參數
    private List<SortParam> sortParams;
    //接口私有查詢參數
    private T param;
}
@Data
public class PageParam extends BaseParam {
    //當前頁
    private int currentPage;
    //每頁顯示大小
    private int pageSize;
    //是否分頁
    private boolean paging;
}
@Data
public class SortParam extends BaseParam{
    //排序字段
    private String fieldName;
    //排序類型
    private String orderType;
}
然後對應的前端參數示例

後臺對應的讀參數方法示例

  public List<Data> getMessageList(@RequestBody PageRequest<ClientLoginParam> request){
    //獲取接口自定義查詢參數
    ClientLoginParam param = request.getParam();
    //獲取分頁參數
    PageParam pageParam = request.getPageParam();
    //獲取排序參數
    List<SortParam> sortParamList = request.sortParams();
    //查詢結果並返回
  }

這裏可以看到,通過Bean定義的方式,確定了前臺的參數格式和參數名稱(配合swagger可以自動生成接口文檔,後面的java架構篇會講解)

這裏有一個很重要的地方要注意,不能用Map接收參數

並不是這種方法不能實現功能,是因爲這種方式給維護代碼帶來很大的不方便性,必須運行時才能確定有哪些參數傳遞過來了,並不能像Bean定義這種方式,通過瀏覽代碼就知道接口主要接收哪些參數。

針對文章剛開始提到的架構觀點

規範性的公共類:必須封裝,必須使用

如果在寫接口的時候,都使用了,基於以上說明的參數類。那麼前端提交的參數格式會非常統一,可維護性大大提高,再也不會出現相同含義的公共參數名稱不同的問題。提高了代碼的整體質量。這就是規範性的東西一定要封裝和使用的原因。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章