編碼風格:Mvc模式下SSM環境,程式碼分層管理

知了一笑發表於2020-11-09

本文原始碼:GitHub·點這裡 || GitEE·點這裡

一、分層策略

MVC模式與程式碼分層策略,MVC全名是ModelViewController即模型-檢視-控制器,作為一種軟體設計典範,用一種業務邏輯、資料、介面顯示分離的方法組織程式碼,將業務邏輯聚集到一個部件裡面,在改進和個性化定製介面及使用者互動的同時,不需要重新編寫業務邏輯,這是一種開發模式,但並不是實際開發中程式碼的分層模式,通常SSM框架的後端程式碼分層如下:

  • controller控制層:定義服務端介面,入參出參,和一些入參校驗;
  • service業務服務層:組裝業務邏輯,業務校驗,構建控制層需要的引數模型;
  • dao資料互動層:提供服務層需要的資料查詢方法,處理資料互動條件相關的邏輯;
  • mapper持久層:基於mybatis框架需要的原生支援,目前很常用的持久層元件;

二、控制層

1、Rest介面風格

基於資源訪問和處理的邏輯,使用不同風格的註解。例如資源新增,更新,查詢,刪除。

/**
 * 新增
 */
@PostMapping("/insert")
public Integer insert (@RequestBody BaseInfo baseInfo){
    return baseInfoService.insert(baseInfo);
}
/**
 * 更新
 */
@PutMapping("/update/{id}")
public String update(@PathVariable(value = "id") Integer id,
                     @RequestBody BaseInfo baseInfo) {
    if (id<1){
        return "error";
    }
    baseInfo.setId(id);
    return "update="+baseInfoService.update(baseInfo);
}
/**
 * 主鍵查詢
 */
@GetMapping("/detail/{id}")
public InfoModel detail(@PathVariable(value = "id") Integer id) {
    return baseInfoService.detail(id) ;
}
/**
 * 主鍵刪除
 */
@DeleteMapping("/delete/{id}")
public String delete(@PathVariable(value = "id") Integer id) {
    baseInfoService.delete(id) ;
    return "SUS" ;
}

2、介面複用度

不建議介面高度複用,例如增刪改查都各自對接介面即可,基本原則,不同的客戶端端操作,對於獨立的介面。

/**
 * 列表載入
 */
@GetMapping("/list")
public List<BaseInfo> list() {
    return baseInfoService.list(new BaseInfoExample()) ;
}
/**
 * 列表搜尋
 */
@PostMapping("/search")
public List<BaseInfo> search (@RequestParam("userName") String userName,
                              @RequestParam("phone") String phone) {
    return baseInfoService.search(userName,phone) ;
}

例如常見的list介面,list通常都有會按條件載入的search機制,而且搜尋的判斷條件很複雜,建議分為兩個介面,從實際考慮,大部分場景下都是隻使用list介面,很少使用search搜尋。

3、入參出參

校驗客戶端必須條件,例如某某條件必填必選等,如果有問題,快速阻斷請求鏈路,做到程式入口控制層攔截返回。

@PutMapping("/update/{id}")
public String update(@PathVariable(value = "id") Integer id,
                     @RequestBody BaseInfo baseInfo) {
    if (id<1){
        return "error";
    }
    baseInfo.setId(id);
    return "update="+baseInfoService.update(baseInfo);
}

引數在三個以下,可以直接陳列入參,引數在三個或三個以上可以使用實體類統一封裝。

@PostMapping("/search")
public List<BaseInfo> search (@RequestParam("userName") String userName,
                              @RequestParam("phone") String phone) {
    return baseInfoService.search(userName,phone) ;
}

4、引數處理

出參格式處理度基本原則,伺服器作為公共資源,避免非必要操作,例如客戶端可自行判斷返回值是否為空,null等,或者一些常見格式處理,利用客戶端適當分擔伺服器壓力。

三、業務服務層

1、業務校驗

例如傳入訂單號,經過資料庫層查詢,沒有訂單資料,這裡稱為業務性質的異常,程式碼本身沒有問題,但是業務邏輯無法正常執行。

public InfoModel detail(Integer id){
    BaseInfo baseInfo = baseInfoDao.selectByPrimaryKey(id) ;
    if (baseInfo != null){
        DetailInfoEntity detailInfoEntity = detailInfoDao.getById(id);
        if (detailInfoEntity == null){
            LOG.info("id="+id+"資料缺失 DetailInfo");
        }
        return buildModel(baseInfo,detailInfoEntity) ;
    }
    LOG.info("id="+id+"資料完全缺失");
    return null ;
}

2、組裝業務邏輯

通常情況下服務層作為邏輯做複雜的一塊,用來拼接業務核心步驟,可以通過業務邏輯判定,一步一步執行程式,避免在程式入口做大量可能用到的物件建立和需求資料查詢。

public int insert (BaseInfo record){
    record.setCreateTime(new Date());
    int insertFlag = baseInfoDao.insert(record);
    if (insertFlag > 0){
        DetailInfoEntity detailInfoEntity = new DetailInfoEntity();
        detailInfoEntity.setUserId(record.getId());
        detailInfoEntity.setCreateTime(record.getCreateTime());
        if(detailInfoDao.save(detailInfoEntity)){
            return insertFlag ;
        }
    }
    return insertFlag;
}

3、資料模型構建

通常情況業務層是偏複雜的,如果想關快速理解業務層,可以對複雜的業務方法,在提供一個返參構建的方法,用來處理服務層要向控制層回傳的引數,這樣可以讓重度的服務層方法變的清晰。

private InfoModel buildModel (BaseInfo baseInfo,DetailInfoEntity detailInfo){
    InfoModel infoModel = new InfoModel() ;
    infoModel.setBaseInfo(baseInfo);
    infoModel.setDetailInfoEntity(detailInfo);
    return infoModel ;
}

四、資料互動層

1、逆向工程

這裡以使用mybatis框架或者mybatis-plus框架作為參考。如果是mybatis框架,建議逆向工程的模板程式碼不做自定義的修改,如果需要自定義方法,在mapper和xml層面再自定義一個擴充套件檔案,用來存放自定義的方法和SQL邏輯,這樣避免表結構變動大引發的強烈不適。

當然現在大部分都會mybatis-plus作為持久層元件,可以避免上述問題。

2、資料互動

針對業務層的需要,提供相應的資料查詢方法,只處理與資料庫互動的邏輯,避免出現業務邏輯,尤其在分散式架構下,不同服務的資料查詢和組裝,不應該出現在該層。

public interface BaseInfoDao {

    int insert(BaseInfo record);

    List<BaseInfo> selectByExample(BaseInfoExample example);

    int updateByPrimaryKey(BaseInfo record);

    BaseInfo selectByPrimaryKey(Integer id);

    int deleteByPrimaryKey(Integer id);

    BaseInfo getById (Integer id) ;
}

五、原始碼地址

GitHub·地址
https://github.com/cicadasmile/data-manage-parent
GitEE·地址
https://gitee.com/cicadasmile/data-manage-parent

推薦閱讀:程式設計體系整理

序號 專案名稱 GitHub地址 GitEE地址 推薦指數
01 Java描述設計模式,演算法,資料結構 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
02 Java基礎、併發、物件導向、Web開發 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆
03 SpringCloud微服務基礎元件案例詳解 GitHub·點這裡 GitEE·點這裡 ☆☆☆
04 SpringCloud微服務架構實戰綜合案例 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
05 SpringBoot框架基礎應用入門到進階 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆
06 SpringBoot框架整合開發常用中介軟體 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
07 資料管理、分散式、架構設計基礎案例 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆
08 大資料系列、儲存、元件、計算等框架 GitHub·點這裡 GitEE·點這裡 ☆☆☆☆☆

相關文章