兩個案例
項目代碼分層
很多同學在代碼結構分層上會參考
開放接口層:可直接封裝 Service 接口暴露成 RPC 接口; 通過 Web 封裝成 http 接口; 網關控
制層等。
終端顯示層:各個端的模板渲染並執行顯示層。 當前主要是 velocity 渲染, JS 渲染, JSP 渲
染,移動端展示層等。
Web 層:主要是對訪問控制進行轉發,各類基本參數校驗,或者不復用的業務簡單處理等。
Service 層:相對具體的業務邏輯服務層。
Manager 層:通用業務處理層,它有如下特徵:
1) 對第三方平臺封裝的層,預處理返回結果及轉化異常信息;
2) 對 Service 層通用能力的下沉,如緩存方案、 中間件通用處理;
3) 與 DAO 層交互,對 DAO 的業務通用能力的封裝。
DAO 層:數據訪問層,與底層 MySQL、 Oracle、 Hbase 進行數據交互。
外部接口或第三方平臺:包括其它部門 RPC 開放接口,基礎平臺,其它公司的 HTTP 接口。
這裏比較有爭議的就是Manager 層與service 層的關係。Manager 層對service 能力的下層,如果我不想service層有相互調用或者在Manager 下層的能力有對service 層的依賴,很容易將破壞上面分層的內在邏輯,不管你怎麼妥協,他不完美。更致命的事,service 在POM上有對manager 的dependency, manager 如何反客爲主呢,maven 是無法循環依賴的。
版本衝突仲裁
默認解決依賴衝突:
第一原則:路徑最近者優先
項目A有如下的依賴關係:
A.SERVICE->POM->PARENT->JSON(1.0)
A.SERVICE->DOMAIN–>JSON(2.0)
則該例子中,JSON的版本是2.0
第二原則:路徑相等,先聲明者優先
項目A有如下的依賴關係:
A.SERVICE->DOMAIN->JSON(1.0)
A.SERVICE->DAO->JSON(2.0)
若pom文件中DOMAIN中的依賴座標先於DAO中進行聲明,則最終JSON的版本爲1.0
手動解決衝突
<dependency>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>project-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>project-b</artifactId>
</exclusion>
</exclusions>
</dependency>
手動依賴排除即可
無法解決的衝突
如果你的項目是安排第一個案例這樣很棒的分層,那麼恭喜你,你很有可能遇到以上兩種方法無法解決的衝突。我曾經遇到這樣的問題,折騰了兩個小時才最終定位。
項目A有如下的依賴關係:
A.DAO(1.0)->POM->JSON(1.0)
A.SERVICE(2.0)->POM->JSON(2.0)
項目A 中最終使用JSON的版本是?
答案是版本2.0
最佳實踐
案例一的最佳實踐
將service 層分拆接口層和實現層。這種情況下,我們解決了循環依賴的同時,可以給予manager 層更多的空間和功能定義。
案例二的最佳實踐
在 A.SERVICE/A.DAO->POM ,在POM中對JSON的版本進行聲明(dependencyManagerment)。分層後的各模塊如果是同機部署,這時依賴衝突的範圍會擴大至整個項目,這個時候除了關心依賴鏈的衝突外,還需關心加載鏈的衝突(個人發明,大家理解下)。
瞎掰工具與架構
maven 是管理包依賴的工具,架構是組織代碼形式和抽象的方法,兩者看似很遠,當我們在架構時充分考慮到12 因素,對於實施中的依賴和構建給予更多的注意力,這時maven 跟架構的關係比想象中近。