1. Model-View-Controller a. 問題 假如開發(fā)一個企業(yè)級應用,只需要一種客戶端的話,那么一切都非常輕易解決。但真實情況是,我們必須面對運行在各種設備上客戶端,象PDA,WAP瀏覽器以及運行在桌面上的瀏覽器,我們不得不開發(fā)不同的應用程序來處理來自不同客戶端的請求。數(shù)據(jù)訪問與現(xiàn)實將混淆在一起,可能會出現(xiàn)重復的數(shù)據(jù)訪問,導致整個開發(fā)周期沒有必要的延長。
2. Front Controller a. 問題 MVC給出了一個整個應用的松散的耦合架構(gòu)。現(xiàn)在來看一下這樣一個經(jīng)常發(fā)生的情況。在某一個應用中,用戶看到的視圖和他所做的操作密切相關(guān)。這是一些具有高度交互性的頁面,而這些頁面之間含有高度的依靠性。在沒有任何模式的時候,這個應用只是一個許多獨立的頁面的集合,維護和擴展變得異常困難。 § 當一個頁面移動后,其他含有這個頁面鏈接的文件,都必須修改。 § 當有一系列頁面需要口令保護時,許多配置文件需要修改,或者頁面需要包含新的標記。 § 當一個頁面需要一個新的表示層時,頁面中的標記要被重新安排。 當這個系統(tǒng)變得復雜時,這些問題將變得更糟。假如用MVC來解決的話,就變成一個如何治理控制器和視圖之間交互的問題。
b. 建議的解決方法 前臺控制模式可以解決這個問題。這個模式中,所有的請求都被傳送到一個對象中。這個主要的對象將處理所有的請求,決定以后顯示那一個視圖,以及實現(xiàn)必要的安全需求。對于把視圖顯示以及其他功能實現(xiàn)集中到一個主要的對象中,將使修改變得很輕易,對應用的修改,可以在所有視圖中反映出來。
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String currentPage= request.getPathInfo(); // get all mapping info for "currentPage" from the hashmap // if "securityCheckRequired = true", do the security check // if "useRequestHandler = true", pass on the incoming request to the specified handler // forward the results to the given "nextScreen" } } 用這種方法實現(xiàn)的控制器將很輕易維護,當應用有新的變動的時候,只要修改XML文件就能解決了。前臺控制模式將使在視圖和控制器之前有復雜交互的J2EE應用變得簡單。
3. session Facade a. 問題 前臺控制給出了一個基于MVC的,能有效治理用戶與J2EE應用之間進行的復雜交互。這個模式可以使處理頁面的現(xiàn)實順序和用戶的并發(fā)請求變得簡單。并且使增加和改變頁面現(xiàn)實變得更加輕易。 另外一個常見的問題是,當EJB或者業(yè)務邏輯發(fā)生變化的時候,應用的客戶端也必須隨之改變。我們來看一下這個問題。 一般來說,為了表現(xiàn)一個賬戶中的用戶,我們使用一個業(yè)務邏輯來表示賬戶中的信息,象用戶名和口令,再用一個EJB來治理用戶的個人信息,象愛好,語言等。當要創(chuàng)建一個新的賬號或者修改一個已經(jīng)存在的賬號時,必須訪問包含賬號信息的EJB,讀取個人信息,修改并且保存,這樣的一個流程。 當然,這只是一個非常簡單的例子,實際情況可能比這個復雜的多,象查看用戶定制了哪些服務,檢驗客戶信用卡的有效性,存放訂單等。在這個案例中,為了實現(xiàn)一個完整的流程,客戶端必須訪問賬戶EJB來完成一系列適當?shù)墓ぷ鳌O旅娴睦语@示了一個Servlet客戶端如何來控制一個用戶訂單。 A servlet that does the workflow required for placing an order // all required imports; // exceptions to be caught appropriately wherever applicable; // This servlet assumes that for placing an order the account and // credit status of the customer has to be checked before getting the // approval and committing the order. For simplicity, the EJBs that // represent the business logic of account, credit status etc are // not listed
public class OrderHandlingServlet extends HttpServlet {
// all required declarations, definitions
public void init() { // all inits required done here }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // other logic as required // Get reference to the required EJBs InitialContext ctxt = new InitialContext(); Object obj = ctxt.lookup("java:comp/env/ejb/UserAccount"); UserAccountHome acctHome = (UserAccountHome) PortableRemoteObject.narrow(obj, UserAccountHome.class); UserAccount acct = acctHome.create(); obj = ctxt.lookup("java:comp/env/ejb/CreditCheck"); CreditCheckHome creditCheckHome = (CreditCheckHome) PortableRemoteObject.narrow(obj, CreditCheckHome.class); CreditCheck credit = creditCheckHome.create(); obj = ctxt.lookup("java:comp/env/ejb/Approvals"); ApprovalsHome apprHome = (ApprovalsHome) PortableRemoteObject.narrow(obj, ApprovalsHome.class); Approvals appr = apprHome.create(); obj = ctxt.lookup("java:comp/env/ejb/CommitOrder"); CommitOrderHome orderHome = (CommitOrderHome) PortableRemoteObject.narrow(obj, CommitOrderHome.class); CommitOrder or