不久前在Jdon網站看到一篇很久的文章,說的是一個小型的Web項目中對MVC的簡單實現,核心的觀點就是:
1.只有一個Controller的servlet 類
2.一個Service接口
3.一些實現Service接口的類
其中Controller類是一個核心的請求分發器,用于對請求進行分配,Service是一個接口,其下有若干個實現類,每個Service實現類其實就是一個具體的業務層邏輯。我注意到其中關于控制的一段核心代碼是這樣的:
try {
//TODO:hashmap to reduce the generated instance?
Class serviceClass = Class.forName(serviceName);
Service service = (Service) serviceClass.newInstance();
service.execute(request, response, servletcontext);
} catch (ClassNotFoundException classnotfoundexception) {
throw new ServletException(classnotfoundexception.getMessage());
} catch (IllegalAccessException illegalaccessexception) {
throw new ServletException(illegalaccessexception.getMessage());
} catch (Exception exception) {
throw new ServletException(exception.getMessage());
}
forward(request, response, targetName);
可以看到它是采用類的動態加載的方式來獲取服務,服務的類型來自于請求的URL,也就是說每個請求后面都會付著一個ServiceName。
個人覺得這是一個不錯的MVC實現。實際上是采用了Command模式。
下面是我對這種方法的一個擴展:(目前僅限于想法,還沒有具體的實現)
·DispatchServlet:
該Servlet是核心控制Servlet,在容器啟動時即被加載,所有的請求都首先被該Servlet所捕捉,根據該請求的類型轉發給相應的子控制器。
·SubController:
當服務比較多且多數的請求可以被歸類成對某一類型的請求時,我們推薦使用SubController(注意:此處的SubController是一個總稱,代表了對應于各個服務類型的請求,實際中可能有UserController、JobController類等)。這樣當中心Servlet將請求轉交到SubController之后,可以由子控制器決定要調用服務層的那個方法。同時可以在此處根據業務需要,設置一些參數,用于控制或指定業務層的業務邏輯處理流程。
·Service:
Service是eFrame中一個核心的接口,它代表了面向客戶的一系列操作集合,如果從設計模式上看可以看成是Facade模式,屏蔽了用戶和多個底層類的直接交互。Service接口有一個ServiceResult execute(Message message)方法,它接受一個Message對象作為服務的參數。并返回一個ServiceResult對象,告訴調用者服務的執行結果和具體內容。
·NonStatusService:
無狀態服務,代表了一次短期完成、不會被打斷的服務。其下有一子類:
·HTTPService:
HTTP服務類,代表了一次HTTP Call,通常是控制器將請求,上下文參數傳給該服務,該服務在實現了業務邏輯后,將響應輸出至頁面
·StatusService:
有狀態服務,代表了一次長時間運行、可能會被隨時中斷的后臺操作,例如從后臺數據庫中取出一批數據發送到客戶端,該服務除了具備其父類的execute方法,還具備了一個表示服務當前狀態的標志,以及啟動、停止、執行服務的方法。
·MMSService:
有狀態服務的一個例子,該例子是用于從后臺數據庫中取出一批數據,然后采用多線程的方式向服務器發送數據由于發送量比較大,可能會被中途中斷。所以系統需要記錄該服務的起始時間、當前狀態。
·ServiceResult:
ServiceResult代表了一次服務的執行結果,它具有兩個常量:SUCCESS和FAILED。分別代表了一次服務的成功執行和失敗。除此之外它還擁有一個用于記錄執行具體結果或返回值的HashMap對象:ResultDetail。
·ServiceLocator:
ServiceLocator是一個服務定位器,用于根據服務類的全稱或者JNDI名稱查找相應的服務類對象,這是一個接口。在其下有一個Service locate(String servieName)方法,用定位服務對象。
·ClassLoaderServiceLocator:使用Java的動態加載機制、反射機制創建服務對象
·JNDIServiceLocator:使用JNDI方式查找加載服務
·ServiceManager:
ServiceManager是一個接口,它用于管理系統中存在的各個Service對象。由于Service對象多數采用動態加載或JNDI查詢的方式產生,所以再性能上會比較慢,由于該類中包含了一個HashMap對象,所有生成的Service對象都會被緩存到其中,所以我們可以對運行時刻的Servcie對象具有完全的控制。
ServiceManager接口包含下列方法:
·register(String serviceId, Service service):注冊一個服務
·get(String serviceId):獲取一個Service對象
·remove(String serviceId):移除一個Service對象
·clear():清空所有的Service對象
ServiceManager有兩個實現類,分別對應于無狀態服務和有狀態服務的管理
·NonStatuesServiceManager:
實現了ServiceManager接口的所有方法
·StautsServiceManager:
除了實現接口的方法之外,還具備了對服務狀態的記錄,服務的啟動、停止的管理
·start(String serviceId):啟動一個服務
·stop(String serviceId):停止一個服務
·getStatus(String serviceId):獲取一個服務
·Message:
Message類代表了一次服務執行中調用者向執行者傳遞的消息。它包含了以下幾個元素:
·messageFrom:消息的來源
·messagTo:消息的接收者
·action:消息的目標動作
·paramters:消息的目標動作執行時所需的參數
此外Message還具備以下方法:
·設置/獲取消息的來源
·設置/獲取消息的目的地
·設置/獲取消息的目標動作
·設置/獲取消息的目標動作所需參數
對Message對象的創建和傳遞通常發生在子控制器調用相應的業務邏輯之前
·AbstractFactory:
AbstractFactory是一個抽象工廠類,它代表了一個能夠根據用戶需求而產生出不同類型對象的工廠,它具有一個抽象的方法
·public abstract Product getProduct(String productType):返回一個指定類型的產品
AbstractFactory下可以有多個繼承的子類,這些繼承的子類都集中于某一類型構建,比如說DaoFactory類
·DaoFactory:
DaoFactory類是繼承了AbstracFactory類的子類,它的目標集中于DAO對象的構建,它返回的是一個實現了Product接口的Dao類實例
·Dao:
Dao類是一個抽象類,它具備了對數據庫操作的一系列基本元素,包括獲取數據庫連接、獲取執行語句,迭代結果集等等。它有3個抽象的方法。分別是:
·public abstract int insert(Object object):插入一個對象
·public abstract int modify(Object object):修改一個對象
·public abstract int delete(Object object):刪除一個對象
由于Dao類對象也屬于工廠中生產出來的產品,所以這里我們讓Dao類實現了Product接口。Dao類下面可以有多個繼承的子類。不同的子類對于如何插入、更新、刪除一個對象是不同的。
·Product:
Product是一個虛擬的概念,它代表了一個從工廠中生產出來的產品。這個接口本身沒有任何的方法
也就是說,每次Web層的請求的處理流程如下:
·Web請求
|--->DispatchServlet
|--->SubController
|--->Service
|--->SubService(NonStatusService / StatusService)
|--->DaoFactory
|--->Dao
|--->SubDao
|--Product
Web頁面<----------------------------------- Domain|
其中在SubController加載相應的Service時,會將相應的參數封裝在Message對象中傳遞給Service對象。服務在執行后會返回一個
ServiceResult對象表示執行的結果情況。
Servcie的加載就像上面提到的可以采用Class.forName,也可以采用JNDI的方式。
附錄:Jdon論壇參考文章地址:一個小的WEB項目中的實現方法討論
-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
posted on 2008-01-09 17:30
Paul Lin 閱讀(2627)
評論(6) 編輯 收藏 所屬分類:
J2EE 框架