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系统开始设计的时候,就要考虑开发、运行、维护阶段的问题