SpringMVC
SpringMVC應該是目前web開發最常用的框架。他的專案結構也相對固定,一般都會有以下幾層。
- controller層
- service層
- mapper介面層
- 實體層
- 可能還有什麼 DTO VO 等層次。
這裡主要講下controller層 和 service層,因為我實際工作中發現,什麼該放在controller層,什麼該放在 service層,似乎每家公司都有自己的做法。
最近一個專案是這樣安排的
public class DepartmentController {
@Autowired
private DepartmentService departmentService;
/**
* 刪除部門
* @param departmentId
* @return
*/
@RequestMapping(value = "/department", method= RequestMethod.DELETE)
public Result delete(String departmentId){
return departmentService.delete(departmentId);
}
}
public class DepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
@Autowired
private UserService userService;
/**
* 刪除部門
* @param departmentId
* @return
*/
@RequestMapping(value = "department", method= RequestMethod.DELETE)
public Result delete(String departmentId){
if(departmentId == null || "".equals(departmentId)){
return new FailResult("部門id不合法");
}
//刪除部門前,檢視部門下是否存在人員
Result result = userService.getUserList(departmentId);
//拆解result 找出結果
List<User> List = result.getDate();
if(if list != null && list.size > 0){
return new FailResult("部門下是否存在人員");
}
int i = departmentService.delete(departmentId);
if(i == 1){
return new SuccessResult<Boolean>(true);
}
return new FailResult("刪除失敗");
}
}
複製程式碼
上面程式碼中,Controller層的任務非常簡單,接收前端的引數然後傳給service,service處理完後返回最終結果,至於 引數傳沒穿,格式對不對,甚至最後返回結果的封裝,都放到service中去處理。
我們可以看到service的任務非常集中,非常重,而Controller的任務非常輕,就只做了一個轉發的操作。其實這樣分配非常不合理,特別是 最終返回結果的封裝,非常不應該放在service裡面。
上面程式碼中我們想刪除一個部門,先要判斷部門下是否存在人員,於是我們呼叫人員的service,結果他返回的是給前端展示的物件,於是我們不得不,拆解物件,取出我們想要的結果,非常麻煩。如果他把Result的封裝放在Controller層就非常方便了,service層可以直接返回處理結果。
經過這次專案後,我一直在思考,Controller層和service層的職責應該怎樣設計才好。下面說下我的看法。
Controller層
Controller層是前端直接接觸的層,離使用者最近,同時也代表著一個介面。
他的任務應該是你按照我的要求傳遞規定的引數,並且引數的值也合法的話,我就返回給你想要的結果。
從上面分析可以看出Controller層關注點在兩個方面,請求引數,和響應結果。
因此,controller層的任務是
- 在呼叫業務層(Serivce)之前,保證業務所需要的引數的個數和內容都要合法。換句話說,在呼叫service之前,service要求的每個引數都要有,並且在內容上要合法,而不要把這些操作延遲都service中去做。
這樣設計的理由也很簡單,你引數都不對,還有必要進入業務層去執行嗎? - 不要讓業務層(Serivce)返回最終結果(前端需要的結果)。這個也很好理解
- mapper層應該返回查詢資料庫的結果。
- service層應該返回業務結果
- controller層應該根據業務層的返回結果做判斷,然後封裝成前端需要的最終結果
所以Controller層的職責總結起來就兩點。
- 在呼叫業務方法之前,保證業務方法所需引數的合法性
- 接收業務方法的返回值,根據返回值做判斷,然後封裝成前端需要的最終結果
Service層
service層負責的是業務的處理,它的關注的是業務,不應該做與業務沒有直接關係的事情。 比如:
- 檢查業務引數的合法性。乍一看好像跟業務相關,但我們換一個角度思考,業務引數不合法就沒有必要進入到業務方法裡面來,再說業務引數是Controller層傳遞過來的,你把不合法的引數傳遞進來是想幹什麼。
- 業務層只返回業務結果,不返回最終結果。這點很容易理解,應為業務結果不一定就是最終結果,業務層只要負責好自己的業務就好了,至於最終結果,當然是由介面(Controller)層去返回。
這樣設計的原因是希望各層職責分明,每層負責自己的事,這樣做還有一個好處,那就是,不會存在某層非常 “重”,而某層又非常 “輕” 的情況。