J2EE寵物商店
作者:◇ 谷和啟 ? 來源:CSDN
 

 J2EE 是Java技術在企業運算上的應用,它包含多種運算標準,如EJB組件架構、JDBC數據庫運算、JMS信息傳遞、Java Servlets/JSP等Web組件程序等,功能強大且內容博大精深。為了讓使用者可以有一個設計J2EE架構應用程序的模板,Sun做出一套系統名為“Java寵物商店(Pet Store)”。這個網上寵物店的范例是針對已經熟悉Java程序設計和J2EE概念人員的。這個系統是使用正規方式設計出來的,使得使用J2EE架構的人員有了一個參考的依據。這個范例一出來,很快就被用來當成比較各家J2EE兼容產品的依據。Oracle的J2EE Application Server(Oracle 9iAS)、BEA WebLogic Server、IBM WebSphere都有相應的產品。Java標準的精神原本就是各家廠商合作制定技術標準,然后再根據這個標準來評選出最優產品。

  Java Pet Store使用的架構設計就是所謂的MVC 設計模式。MVC是Model-View-Controller的簡寫,是設計模式的一種,源自Smalltalk。MVC模式則是將對象分成三類,Model對象專門用來包裝應用程序的狀態,View用來負責屏幕上的展現,Controller則負責定義應用程序的各種動作和反應。Java寵物店系統利用MVC模式設計整個系統架構,將各層的對象清楚地分開。Java寵物店的目的是展示一個具有擴充性的企業運算架構,就是采用三層(3-Tiers)式設計:資料展現層在最外面,中間是執行企業運算邏輯的中間層組件,后端就是單純存放資料的關系型數據庫。Java寵物店當初的用意也只是當成一個J2EE架構設計的模板,并沒有特別針對加速執行效能作額外的設計。

系統構架與寵物商店簡介

  系統構架

  Pet Store網站系統采用松耦合的設計架構,可以和多個數據源、EIS進行交互。這個例子共分成4個部分:

  1.Web購物站點;

  2.管理部分,包括銷售統計、手工接受/拒絕訂單;

  3.訂單處理,包括以下4部分內容:

   ◆ 通過JMS接受/處理訂單消息;

   ◆ 用Java Mail來通知客戶;

   ◆ 通過JMS發訂單給供應商;

  ◆ 維護訂單數據庫。

  4.供應商,此部分包括以下內容:

   ◆ 通過JMS接受訂單;

  ◆ 派送貨物給用戶;

  ◆ 提供一個基于Web的庫存管理;

  ◆ 維護庫存數據庫。

  寵物店網上商店功能

  通過瀏覽器可以訪問此商店。客戶通過瀏覽,可以把貨物放入購物車,創建賬戶/登錄賬戶,創建訂單,然后通過信用卡支付。

  寵物商店結構

  寵物店的網站服務是從上而下的。最上層是WAF(Web Application Framework)來控制應用的屏幕跳轉,產生視圖,然后調用商業組件來完成商業處理(如圖1所示)。



  圖1 Java Pet Store 結構

  WAF提供了許多Web應用所需的服務,包括請求的過濾和分發、模板視圖的產生、一系列可重用的Taglib,以及屏幕流程控制等。應用組件封裝了處理的邏輯,它們代表了商業的數據,并且操作這些商業數據,實體EJB代表了商業實體,如客戶、地址、賬目。會話EJB提供了一些方法,如登陸一個用戶、輸出一個用戶、管理購物車等。其它會話EJB提供了一些共同的方法,如產生唯一標示符。傳統的JavaBean組件變成了值對象,用來在EJB組件和應用間傳遞數據。XML文檔類則用來處理訂單信息。

  這個寵物店例子的WAF是對J2EE藍圖Web層規范的實現。一個Web層處理一般可以劃分成四步(如圖2所示):

  ◆ 解釋一個請求;

  ◆ 執行一個商業邏輯處理;

  ◆ 選擇下一個視圖;

  ◆ 產生這個視圖。



  圖2 WAF的Web層處理

  寵物店模塊設計

  寵物店由一些獨立模塊組成:

  ◆ 控制模塊 它來分發請求到各個業務處理邏輯、控制屏幕跳轉、處理對應的組件及用戶;

  ◆ 登錄和注冊 控制模塊由WAF實現和擴展;

  ◆ 購物車模塊 購物車跟蹤用戶購物過程;

  ◆ 登錄模塊 需要用戶登錄在某些頁面登錄;

  ◆ 消息模塊 從寵物店到等單中心用來異步傳輸訂單;

  ◆ 類別模塊 根據用戶查詢需求提供一個類別視圖;

  ◆ 客戶模塊 表示客戶信息,如地址、信用卡、聯系方式等(如圖3所示)。



  圖3 Java pet Store 模塊設計

  在圖3中,控制模塊控制所有的交互和執行,每個用戶會話都有一個購物車對應。

  寵物店的組件

  1. EJB,代表了商業數據和執行商業邏輯處理;

  2. JSP頁面, 定義了整個應用的視圖框架模板(template.jsp)和模板組成的各個JSP文件,以及各種被引用的圖形文件;

  3. XML文件,用來定義屏幕、屏幕跳轉控制、綁定URL到某個HTML Action、定制signOn以及J2EE部署的部署XML文件;

  4. Servlet過慮器, 用來校驗用戶安全的登陸和輸出的編碼;

  5. 異步信息發送組件,傳輸使用XML封裝的訂單到訂單處理中心;

  6. 一個安裝程序,用來產生例子數據庫。

分析寵物商店的應用

下面就按照MVC架構和層次化應用模型來分析這個應用。

模型—視圖—控制架構

1.應用模型劃分方法

分析一個實際應用可以有三種劃分的方法:第一種劃分方法為模型—視圖—控制(MVC)架構。這種方法把應用分解成數據、顯示和控制三個部分。第二種劃分方法把應用按照不同的角色劃分成不同的層次,分離客戶端、Web層、EJBs層和底端的數據層或遺留系統層,即J2EE應用的層次劃分方法。第三種劃分是傳統的功能模塊劃分。

劃分的目的是使復雜的問題清晰化、條理化。每一種劃分雖然增加了額外的復雜性,但也有它的好處。MVC架構為應用組件提供一個靈活的、可重用的、易測試的、可擴展的和清晰的設計角色。多層設計使實現技術的選擇靈活,同時具有可升級和可擴展性。模塊化的設計把系統分解成小的直接模塊,可以進行單獨分析、測試和理解。

現在企業級應用與以前相比,要更多地支持使用不同類型接口的多類型用戶,例如在線商店需要為Web顧客提供HMTL主頁、為無線顧客提供XML主頁、為系統管理員提供JFC/Swing接口、為供應商提供基于XML的Web服務等(見圖4)。



圖4 Java Pet Store 支持的各種類型用戶關系圖

當開發一個支持單一類型客戶端的應用時,可以把數據訪問邏輯、顯示控制邏輯和接口邏輯交織在一起。但對于支持多類型客戶端的企業系統來說,這是很麻煩的。因此:

◆ 對于每種類型的客戶端接口,需開發不同的應用;

◆ 每個應用的非界面代碼是重復的,在實現、測試和維護方面需重復工作;

◆ 復制工作本身是昂貴的,因為界面與非界面代碼交織;

◆ 重復工作不可避免,而且是有缺陷而緩慢的。

2.使用模型—視圖—控制架構

通過在J2EE應用中使用模型—視圖—控制架構,把核心數據和數據訪問功能與使用這些功能的顯示控制邏輯分開,如圖5所示。這種分離允許多視圖共享同樣的企業數據模型。



圖5 MVC架構

MVC架構起源于Smalltalk,最初用來在傳統的圖形用戶界面模型中映射輸入、處理和輸出任務。然而,它可以直接用來映射多層企業應用中的相關概念,具體概念介紹如下:

模型(Model)代表企業數據和業務規則,用來控制訪問和數據更新。模型是接近現實世界的服務軟件,因此現實世界的建模技術可以應用模型。

視圖(View)代表模型的內容。它通過模型訪問企業數據并指定這些數據的顯示。視圖負責模型狀態改變后呈現給用戶的數據也相應改變。可以通過推(Push)模型實現,即視圖在模型中注冊獲取更新指令,或者拉(Pull)模型,即由視圖負責在需要獲取最新數據的時候調用模型。

控制(Controller)把與視圖交互轉化成模型執行的動作。在獨立運行的GUI客戶端,用戶交互可能是按鈕或菜單,而在Web應用中是GET和POST HTTP請求。模型執行的動作包括激活業務處理進程或改變模型狀態。以用戶交互和模型動作結果為基礎,控制通過選擇合適的視圖完成相應功能。

MVC架構有如下優點:

◆ 多視圖使用同一模型。模型與視圖分離允許多視圖使用同一企業模型。因此,企業級應用模型組件容易實現、測試和維護。

◆ 容易支持新類型的客戶端。支持一個新類型的客戶端,只需寫一個視圖和控制,然后把它連到現存的企業模型中。

分析Java Pet Store應用

視圖

視圖是用戶界面和應用程序的接口。在Java Pet Store中,視圖在Web層實現。共有三種組件實現視圖:JSP頁面、JSP自定義標記和JavaBean。視圖部分涉及到三方面內容:

1.屏幕

屏幕是一個頁面顯示的所有內容。根據需要,在ScreenDefinitions.jsp中定義如下屏幕:

																												
																														
Name:MAIN_SCREEN,DEFAULT_SCREEN
    Name:CATEGORY_SCREEN
    Name:SEARCH_SCREEN
    Name:PRODUCT_SCREEN
    Name:PRODUCT_DETAILS_SCREEN
    Name:CART_SCREEN
    Name:CHECKOUT_SCREEN
    Name:PLACEORDER_SCREEN
    Name:COMMIT_ORDER_SCREEN
    Name:SIGNIN_SCREEN
    Name:SIGNUP_SCREEN
																												
																										


2.模板

因為要使整個網站的頁面具有相同的特征,如每個頁面都要有Logo、Banner等相同的元素,所以采用模板定義頁面的不同組成部分。本示例中定義的模板元素有footer.jsp、banner.jsp和index.jsp等。ScreenDefinitions.jsp定義好的屏幕包括這些模板元素,通過include指令包含到頁面中

3.視圖選擇

視圖的選擇是通過控制來完成的。控制根據實際情況分析用戶顯示視圖的ID,運行模板把整個視圖顯示出來,如圖6所示。



圖6 視圖選擇

模型

模型的狀態是視圖顯示的數據來源,也是控制的具體對象。在J2EE中,描述模型的狀態采用三種EJB:無狀態會話EJB、有狀態會話EJB和實體EJB。

1.輔助對象

有兩種主要的輔助對象:數據庫訪問對象和值對象。對于實體EJB來說,數據庫訪問對象封裝了數據庫訪問的方法,如AccountDAO等。對于所有EJB的屬性值,則都由一個值對象來封裝,如ShoppingCartModel、AccountModel等。

2.EJBs

本示例用到的EJBs如圖7所示。



圖7 Java Pet Store使用到的EJBs

3.模型狀態到視圖的綁定

一個模型對應多個視圖,實現視圖的綁定方法是:ModelUpdateListener和ModelUpdateNotifier實現了一種注冊-監聽模式,通過調用監聽器的performUpdate方法來使視圖得到更新。例如:

																																		
																																				
public class AccountWebImpl extends AccountModel
implements ModelUpdateListener{
 private ModelManager mm;
 private Account acctEjb;
 public AccountWebImpl(ModelManager mm){
  super(null,null,null};
  this.mm=mm;
  mm.addListener(JNDINames.ACCOUNT_EJBHOME,this);
 }
 public void performUpdate(){
  if(acctEjb==null)  {
   acctEjb=mm.getAccountEJB();
  }
  try{
   if(acctEjb !=null)copy(acctEjb.getDetails());
  }catch(RemoteException re){
   throw new GeneralFailureException(re);
  }
 }
}
																																		
																																


控制

控制負責處理用戶請求、調用相應的模型、更新模型的狀態、刷新視圖以及返回用戶合理的頁面。示例的所有控制對象如圖8所示。



圖8 控制對象圖

1.RequestProcessor

RequestProcessor接收并處理用戶的所有請求,調用RequestToEventTranslator對象把請求轉換成預定義的事件,在事件處理完成后,進行視圖更新。 代碼如下所示:

																																		
																																				
public class RequestProcessor{
     private ShoppingClientControllerWebImpl scc;
     private ModelManager mm;
     private ModelUpdateNotifier mun;
     private RequestToEventTranslator eventTranslator;
     private SecurityAdapter securityAdapter;
     public void init(...)  {
      mm = (ModelManager)session.getAttribute("modelManager");
      mun = mm;
      SCC = new ShoppingClientControllerWebImpl(session);
      eventTranslator= new RequestToEventTranslator(this,mm);
     }
     public void processRequest(HttpServletRequest req){
      checkForWebServerLogin(req);
      EStoreEvent event = eventTranslator.processRequest(req);
      if (event != null){
       Collection updatedModelList = scc.handleEvent(event);
       mun.notifyListeners(updatedModelList);
      }     
     }
    }
																																		
																																


2.ShoppingClientControllerWebImpl

ShoppingClientContronerWebImpl是調用EJB層的ShoppingClientController代理對象,代碼如下所示:

																																		
																																				
public class ShoppingClientControllerWebImpl{
     private com....ejb.ShoppingClientController sccEjb;
     private HttpSession session;
     public ShoppingClientControllerWebImpl(HttpSession session){
      this.session = session;   
      ModelManager mm= (ModelManager)session.getAttribute("modelManager");
      sccEjb = mm.getSCCEJB();    
     }
     public synchronized AccountModel getAccount(){
      return sccEjb.getAccount().getDetails();
     }    
     ......   
     public synchronized Collection handleEvent(EStoreEvent ese){
      return sccEjb.handleEvent(ese);
     }
     public synchronized void remove()  {
      sccEjb.remove();
     }
    }
																																		
																																


3.ShoppingClientController

ShoppingClientController是有狀態的會話EJB,它為每個用戶建立一個單獨的實例,負責購物車和賬號的生命周期,并負責處理事件。同時它也控制狀態機StateMachine的生命周期。代碼參見賽迪網http://linux.ccidnet.com的期刊瀏覽2003年第6期。

4.StateMachine

StateMachine實現核心的業務邏輯,它負責改變模型的狀態,包括處理每個業務事件的方法。代碼參見賽迪網http://linux.ccidnet.com的期刊瀏覽2003年第6期。

  小結

  J2EE網站的開發方法,即是Internet的開發方法。Internet開發的發展可以劃分為三個階段:第一階段是將業務邏輯和表現邏輯完全集成在一起,采用HTML、JSP和Servlets技術開發;第二階段是將業務邏輯和表現邏輯分開,采用HTML、JSP、Servlets、JavaBeans Compoments和Custom Tags技術開發;第三個階段是MVC設計模式(J2EE的開發方法)。今天,MVC設計模式已成為Internet開發發展的主流。無論是通過第一階段開發的應用,還是通過第二階段開發的應用,都會面臨著開發人員的分工、應用的可維護性和可擴展性及可測量性的問題。為此,我們在設計階段關心的重點是系統結構的復雜程度、代碼之間的耦合度、代碼的易維護性、應用框架的可重用性、EJB組件的可重用性和易測試性,以及不同技能開發人員的分工等。用縱觀全局的眼光來看,在Internet系統開始設計的時候,就要考慮開發、運行、維護階段的問題