close

 

  寫物件導向的Web端程式的人,最開始入手的架構概念叫做MVC,MVC的架構概念很簡單,就是把工作分成M→Model,V→View,C→Controller,Model即是資料,而View則是呈現給使用者的UI,而Controller負責邏輯處理;這就是MVC的基本概念,這三者間的分工,也協助了工程師之間的分工,負責前端UI的工程師,針對Model與View之間的關係進行處理;而負責後端Server的工程師,則針對Model與Controller之間的關係進行處理。

上述說的是一般的Web工程師,最早遇到的架構概念,但是當我們深入到後端Server中,會發現Model與Controller之間的關係,並不是那麼的簡單,而是更複雜地分了好幾層來進行二者之間的邏輯處理,最常見的是:

  在Model與Controller之間,建立了Action(Controller)、Service(Manager)、Dao,三層式的架構(下方簡稱三層式架構)。

Action(Controller)其實很容易理解,它是用來承接前端進入的入口;Dao也很容易理解,因為它是將DB的資料轉換為物件的程式;不過中間的Service(Manager),是做什麼的呢?為什麼要弄得這麼複雜呢?

 

會建立中間的Service(Manager)層是有原因的,它是為了解決實際上進行時,會遇到某些問題而發展出來的,我們下方來看個例子。

經典問題:轉帳

如果各位讀者有上過任何關於資料庫的課,或是看過任何關於資料庫的書,多多少少都會提到這個「轉帳」的經典問題,這個問題的也很簡單,問題的內容就是「A想要轉一筆錢給B」,單純只有這樣;不過切換到在現行的系統下,它會變成三個動作:

  1. 第一個動作-A扣錢

  2. 第二個動作-判斷A的錢是否大於0

  3. 第二個動作-B加錢

這三個動作可以沒有順序性,重點是不論那一個失敗,都必須將另外二個動作復原,依此原理,牽扯出資料庫的「交易(Transaction)」用法;同樣的,這個問題也適用在我們後端的程式上。

當我們實作上述幾個動作時,在Dao層,大概只會有下列幾個功能:

很明顯可以看到,我們並沒有針對轉帳的功能來實作,而只有針對某人的金額做操作,與取得某人的金額而已。

不過,當我們想要以這二個方法來實作「轉帳」功能的話,很明顯它是不夠的,因為我們還需要Transaction的功能,所以我們必須在呼叫這二個Method的外圍,包一個Transaction後,才能達成交易失敗後的回復(rollback);而這二個Method的外圍,那不就是Action層了嗎?這樣變我們直接在Action層中操作資料庫啦!!

很明顯,這樣的二層式架構是不夠的,為了解決這個問題,所以多包了一個Service(Manager)層。如果多包了一個Service層的話,那Service層的程式會變成:

在Service層的實作中,開一個Transaction後,再呼叫Dao的二個Method,即可以完成整個「轉帳」的交易,實作如下:

而Action層只需要呼叫Service層的一個Method,就可以完成轉帳的動作;這樣,我們就不用在Action層來處理Transaction的問題了,而且Dao也可以簡單的處理資料,不需要去考慮Transaction的問題。

範例網站

當我們瞭解到三層式架構的原理後,我們來看看在JAVA網站中,是怎麼去實作這種三層式架構的。下方我們會使用Appfuse的網站中的Spring + Struts2 + hibernate網站當範例,而這個網站的範例中使用了Spring AOP的功能來完成這件事情,Spring AOP又是一門學問了,在這邊不討論。

我們可以看到這個範例網站中的src/main/resources/applicationContext-dao.xml,宣告了一個transactionManager。

這個transactionManager由org.springframework.orm.hibernate4.HibernateTransactionManager所控管,從官網中可以得知,它會針對sessionFactory中所取得的JDBC session連線,進行transaction的功能。

之後,在src/main/resources/applicationContext-service.xml中,可以發現如下程式:

其中,tx:advice中有一個attribute是transaction-manager,預設為transactionManager,所以上方的程式等同:

最後,在同一份src/main/resources/applicationContext-service.xml的上方程式中,可以找到這樣的設定:

因為此功能設定牽扯Spring的AOP,所以這邊不做詳細解釋,不過讀者可以大概的瞭解到,所有*.*..service.*Manager.*中的所有Method都會被包一個Transaction起來,如果是這樣的話,則剛剛的Service層的程式則可以改成:

我們可以和上方的程式比較一下,由原本的28行變為16行,原因是Transaction的部份由Spring AOP中宣告的transactionManager處理掉了,所以當我們需要它做rollback時,記得要丟Exception出去。

**重要:千萬不要自己去做try catch的動作,否則程式不會知道要進行rollback。

結論

瞭解了三層式的架構的分工後,我們就可以知道我們的商業邏輯的擺放位置,簡單的區分如下:

  • Dao層      →存放資料庫轉Model物件的邏輯。

  • Service層 →存放需要進行交易的邏輯。

  • Action層   →其他商業邏輯。

另外,即使明知這個動作並不需要有Transaction的動作,也還是建議Action不要直接呼叫Dao層,透過Service層來呼叫Dao,這樣整個網站的邏輯才會統一,在閱讀與修改上都會比較直覺一點。

arrow
arrow

    JAVA Programmer 發表在 痞客邦 留言(1) 人氣()