溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析

發(fā)布時間:2021-10-31 17:24:34 來源:億速云 閱讀:875 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了“java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析”這篇文章吧。

MVC三層架構(gòu)

我們在剛剛成為程序員的時候,就會被前輩們 “教育” 說系統(tǒng)的設計要遵循 MVC(Model-View-Controller)架構(gòu)。它將整體的系統(tǒng)分成了 Model(模型),View(視圖)和 Controller(控制器)三個層次,也就是將用戶視圖和業(yè)務處理隔離開,并且通過控制器連接起來,很好地實現(xiàn)了表現(xiàn)和邏輯的解耦,是一種標準的軟件分層架構(gòu)。

java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析

MVC分層架構(gòu)是架構(gòu)上最簡單的一種分層方式。為了遵循這種分層架構(gòu)我們在構(gòu)建項目時往往會建立這樣三個目錄:controller、service 和 dao,它們分別對應了表現(xiàn)層、邏輯層還有數(shù)據(jù)訪問層。

java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析

每層的作用如下:

Controller層:主要是對訪問控制進行轉(zhuǎn)發(fā),各類基本參數(shù)校驗,或者不復用的業(yè)務簡單處理。

Service層:主要是處理業(yè)務邏輯和事務

Dao層:負責與底層數(shù)據(jù)庫MySQL,Oracle等進行數(shù)據(jù)交互

可是隨著我們的業(yè)務邏輯越來復雜,代碼寫的越來越多,這種簡單的三層架構(gòu)的問題也越來越明顯。

MVC架構(gòu)弊端

傳統(tǒng)的MVC分層有以下幾個很明顯的問題:

Service層代碼臃腫

Service層很容易出現(xiàn)大事務,事務嵌套,導致問題很多,而且極難排查

dao層參雜業(yè)務邏輯

dao層sql語句復雜,關聯(lián)查詢比較多

為了解決這個問題,我們參考《alibaba java開發(fā)手冊》,在Service層之下再獨立出一個通用業(yè)務處理層(Manager層)

java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析

在這個分層架構(gòu)中主要增加了 Manager 層,它與 Service 層的關系是:Manager 層提供原子的服務接口,Service 層負責依據(jù)業(yè)務邏輯來編排原子接口。

Manager層的特征

在《alibaba java開發(fā)手冊》中是這樣描述Manager層的:

Manager 層:通用業(yè)務處理層,它有如下特征:

對第三方平臺封裝的層,預處理返回結(jié)果及轉(zhuǎn)化異常信息,適配上層接口;對 Service 層通用能力的下沉,如緩存方案、中間件通用處理;與 DAO 層交互,對多個 DAO 的組合復用。

在實際開發(fā)中我們可以這樣使用Manager層

復雜業(yè)務,service提供數(shù)據(jù)給Manager層,負責業(yè)務編排,然后把事務下沉到Manager層,Manager層不允許相互調(diào)用,不會出現(xiàn)事務嵌套。

專注于不帶業(yè)務sql語言,也可以在manager層進行通用業(yè)務的dao層封裝。

避免復雜的join查詢,數(shù)據(jù)庫壓力比java大很多,所以要嚴格控制好sql,所以可以在manager層進行拆分,比如復雜查詢。

當然對于簡單的業(yè)務,可以不使用Manager層。

Manager層使用案例

這里我們舉個例子說明一下Manager層的使用場景:

假設你有一個用戶系統(tǒng),他有一個獲取用戶信息的接口,它調(diào)用邏輯Service層的 getUser 方法,getUser方法又和 User DB 交互獲取數(shù)據(jù)。如下圖左邊展示部分。

這時,產(chǎn)品提出一個需求,在 APP 中展示用戶信息的時候,如果用戶不存在,那么要自動給用戶創(chuàng)建一個用戶。同時,要做一個 HTML5 的頁面,HTML5 頁面要保留之前的邏輯,也就是不需要創(chuàng)建用戶。

java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析

此時按照傳統(tǒng)的三層架構(gòu),邏輯層的邊界就變得不清晰,表現(xiàn)層也承擔了一部分的業(yè)務邏輯,因為我們往往會在表現(xiàn)層Controller中增加業(yè)務邏輯處理,將獲取用戶和創(chuàng)建用戶接口編排起來。

而添加Manager層以后,Manager 層提供創(chuàng)建用戶和獲取用戶信息的接口,而 Service 層負責將這兩個接口組裝起來。這樣就把原先散布在表現(xiàn)層的業(yè)務邏輯都統(tǒng)一到了 Service 層,每一層的邊界就非常清晰了。

接下來我們看一段實際代碼說明一下Service層與Manager層如何進行區(qū)分?

@Transactional(rollbackFor = Throwable.class)
public Result<String> upOrDown(Long departmentId, Long swapId) {
  // 驗證 1
  DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
  if (departmentEntity == null) {
    return Result.error("部門xxx不存在");
  }
  // 驗證 2
  DepartmentEntity swapEntity = departmentDao.selectById(swapId);
  if (swapEntity == null) {
    return Result.error("部門xxx不存在");
  }
  // 驗證 3
  Long count = employeeDao.countByDepartmentId(departmentId);
  if (count != null && count > 0) {
    return Result.error("員工不存在");
  }
  // 操作數(shù)據(jù)庫 4
  Long departmentSort = departmentEntity.getSort();
  departmentEntity.setSort(swapEntity.getSort());
  departmentDao.updateById(departmentEntity);
  swapEntity.setSort(departmentSort);
  departmentDao.updateById(swapEntity);
  return Result.OK("success");
}

上面代碼在我們在我們采用三層架構(gòu)時經(jīng)常會遇到,那么它有什么問題呢?

上面的代碼是典型的長事務問題(類似的還有調(diào)用第三方接口),前三步都是使用 connection 進行驗證操作,但是由于方法上有@Transactional 注解,所以這三個驗證都是使用的同一個 connection。

若對于復雜業(yè)務、復雜的驗證邏輯,會導致整個驗證過程始終占用該 connection 連接,占用時間可能會很長,直至方法結(jié)束,connection 才會交還給數(shù)據(jù)庫連接池。

對于復雜業(yè)務的不可預計的情況,長時間占用同一個 connection 連接不是好的事情,應該盡量縮短占用時間。

說明:對于@Transactional 注解,當 spring 遇到該注解時,會自動從數(shù)據(jù)庫連接池中獲取 connection,并開啟事務然后綁定到 ThreadLocal 上,如果業(yè)務并沒有進入到最終的 操作數(shù)據(jù)庫環(huán)節(jié),那么就沒有必要獲取連接并開啟事務,應該直接將 connection 返回給數(shù)據(jù)庫連接池,供其他使用。

所以我們在加入Manager層以后可以這樣寫:

DepartmentService.java 
public Result<String> upOrDown(Long departmentId, Long swapId) {
  // 驗證 1
  DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
  if (departmentEntity == null) {
    return Result.error("部門xxx不存在");
  }
  // 驗證 2
  DepartmentEntity swapEntity = departmentDao.selectById(swapId);
  if (swapEntity == null) {
    return Result.error("部門xxx不存在");
  }
  // 驗證 3
  Long count = employeeDao.countByDepartmentId(departmentId);
  if (count != null && count > 0) {
    return Result.error("員工不存在");
  }
  // 操作數(shù)據(jù)庫 4
  departmentManager.upOrDown(departmentSort,swapEntity);
  return Result.OK("success");
}
DepartmentManager.java
  
@Transactional(rollbackFor = Throwable.class)
public void upOrDown(DepartmentEntity departmentEntity ,DepartmentEntity swapEntity){
  Long departmentSort = departmentEntity.getSort();
  departmentEntity.setSort(swapEntity.getSort());
  departmentDao.updateById(departmentEntity);
  swapEntity.setSort(departmentSort);
  departmentDao.updateById(swapEntity);
}

將數(shù)據(jù)在 service 層準備好,然后傳遞給 manager 層,由 manager 層添加 @Transactional事務注解進行數(shù)據(jù)庫操作。

以上是“java開發(fā)MVC三層架構(gòu)上再加一層Manager層原理的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI