Java Web應用的代碼分層最佳實踐。

代碼分層,對於任何一個Java Web開發來講應該都不陌生。一個好的層次劃分不只能夠能使代碼結構更加清楚,還可使項目分工更加明確,可讀性大大提高,更加有利於後期的維護和升級。數據庫

從另一個角度來看,好的代碼分層架構,應該是能夠很好的匹配上單一職責原則的。這樣就能夠下降層與層之間的依賴,還能最大程度的複用各層的邏輯。本文就來介紹下Java Web項目的代碼到底應該如何分層。緩存

三層架構

在軟件體系架構設計中,分層式結構是最多見,也是最重要的一種結構。微軟推薦的分層式結構通常分爲三層,從下至上分別爲:數據訪問層、業務邏輯層(又或稱爲領域層)、表示層。這也是Java Web中重要的三層架構中的三個層次。區分層次的目的即爲了「高內聚低耦合」的思想。安全

所謂三層體系結構,是在客戶端與數據庫之間加入了一個「中間層」,也叫組件層。這裏所說的三層體系,不是指物理上的三層,不是簡單地放置三臺機器就是三層體系結構,也不只僅有B/S應用纔是三層體系結構,三層是指邏輯上的三層,即把這三個層放置到一臺機器上。架構

數據訪問層

主要是對非原始數據(數據庫或者文本文件等存放數據的形式)的操做層,而不是指原始數據,也就是說,是對數據庫的操做,而不是數據,具體爲業務邏輯層或表示層提供數據服務。微服務

業務邏輯層

主要是針對具體的問題的操做,也能夠理解成對數據層的操做,對數據業務邏輯處理,若是說數據層是積木,那邏輯層就是對這些積木的搭建。網站

界面層

主要表示WEB方式。若是邏輯層至關強大和完善,不管表現層如何定義和更改,邏輯層都能完善地提供服務。spa

三層架構與MVC的區別

MVC(模型Model-視圖View-控制器Controller)是一種架構模式,能夠用它來建立在域對象和UI表示層對象之間的區分。架構設計

MVC

一樣是架構級別的,相同的地方在於他們都有一個表現層,可是他們不一樣的地方在於其餘的兩個層。設計

在三層架構中沒有定義Controller的概念。這是最不一樣的地方。而MVC也沒有把業務的邏輯訪問當作兩個層,這是採用三層架構或MVC搭建程序最主要的區別。3d

3

更加細緻的分層

隨着網站的用戶量的不斷提高,系統架構也在不斷的調整。有時候,隨着業務愈來愈複雜,有時候三層架構好像不夠用了。好比,咱們的應用除了要給用戶提供頁面訪問之外,還須要提供一些開放接口,供外部系統調用。這個接口既不屬於界面層,也不該該屬於業務邏輯層,由於他還可能包含一些和業務邏輯無關的處理,如權限控制、流量控制等。

還有,隨着微服務的盛行,咱們應用中可能要依賴不少外部接口或第三方平臺。這部分代碼放下業務邏輯層和數據訪問層也都不合適。

因此,漸漸的,在三層架構的基礎上,系統架構的分層變得更加複雜了。也正是由於複雜,就很是考驗架構設計能力,由於層次劃分的很差,極可能會影響後面的開發,給代碼維護帶來很大的困難。

下圖,是阿里巴巴(參考《阿里巴巴Java開發手冊》)提倡的應用分層結構:

ceng

開放接口層

可直接封裝 Service 方法暴露成 RPC 接口;經過 Web 封裝成 http 接口;進行網關安全控制、流量控制等。

終端顯示層

各個端的模板渲染並執行顯示的層。當前主要是 velocity 渲染,JS 渲染,JSP 渲染,移動端展現等。

Web 層

主要是對訪問控制進行轉發,各種基本參數校驗,或者不復用的業務簡單處理等。

Service 層

相對具體的業務邏輯服務層。

Manager 層

通用業務處理層,它有以下特徵: 1) 對第三方平臺封裝的層,預處理返回結果及轉化異常信息; 2) 對 Service 層通用能力的下沉,如緩存方案、中間件通用處理; 3) 與 DAO 層交互,對多個 DAO 的組合複用。

DAO 層

數據訪問層,與底層 MySQL、Oracle、Hbase 等進行數據交互。

外部接口或第三方平臺

包括其它部門 RPC 開放接口,基礎平臺,其它公司的 HTTP 接口。

事務處理

在瞭解了分層以後,咱們再來看一下寫Java Web代碼的時候,你們比較關心的一個問題,那就是涉及到數據庫操做的時候,事務處理應該在哪一層控制呢?

關於這個問題,仁者見仁,智者見智。做者認爲,事務處理應該放在Service層和Manager層。

DAO層不該該有事務,應該只是很純的 CRUD 等比較通用的數據訪問方法。一個DAO應該只處理和本身相關的操做,不要有任何組合。組合的事情交給上層。

Service層和Manager層通常會組合多個DAO的CRUD操做,例如:在註冊一個用戶的時候須要往日誌表裏 INSERT 日誌,那麼就在 Service 層構造事務,在該事務中調用 Dao 層的 User.Insert () 與 Log.Insert ()。

異常處理

異常處理是Java中比較重要的一個話題,在《Effective Java》中有不少關於異常處理的最佳實踐,這裏不詳細介紹了,本文主要簡單說一下在應用代碼分層以後,各個層次之間的異常應該如何處理,是本身捕獲,仍是向上一層拋出。

首先,每一層都是可能發生異常的。因爲每一層的職責都不通,處理方式也可能有差異。

DAO層

在 DAO 層,產生的異常類型可能有不少,多是SQL相關的異常,也多是數據庫鏈接相關的異常。

這一層的處理方式能夠簡單一點,直接try-catch(Exception),而後封裝成DAOException拋給上一層。這一層通常不須要打印日誌,交給Service或者Manager層來打印。

try{
    CRUD
}catch(Exception e){
    throw new DAOException(e);
}
複製代碼

Manager/Service

首先,對於DAO層拋上來的異常必定要捕獲的,而且記錄日誌打印現場。

可是值得注意的是,若是是須要事務控制的方法,要注意捕獲到異常以後再向上拋一個新的異常,如 TransactionRolledbackException,不然事務沒法回滾。

這兩層發生的異常能夠根據狀況決定是繼續向上拋仍是本身處理掉。若是是本身能夠處理的異常,就捕獲,打日誌,而後經過ErrorCode等方式返回給上一層。若是是本身沒法處理或者不知道該如何處理的異常,就直接拋給上一層來處理。

Web

首先,能夠明確的一點:Web層不該該再往外拋異常,由於這一層一旦拋異常,就可能會致使用戶跳轉到不友好的錯誤頁面甚至看到錯誤信息等。

若是意識到這個異常將致使頁面沒法正常渲染,那麼就應該直接跳轉到友好錯誤頁面,加上用戶容易理解的錯誤提示信息。

開放接口層

這一層和Web層同樣,不能夠拋出異常。通常經過ErrorCode和ErrorMessage反饋給外部調用方。

這一層,要本身處理好全部的異常,定義好ErrorCode,並記錄好日誌,便於往後排查問題。

總結

本文主要介紹了Java Web項目中代碼分層的方案,經過分層以後可使沒一層更加專一,解除耦合。並簡單介紹了一下分層以後的事務處理和異常處理的邏輯。

相關文章
相關標籤/搜索