UML软件工程组织

软件体系架构模式在J2EE中的应用
刘兵 (cnj2ee@tom.com)
技术顾问 , 软件公司  来自:IBM中国  2003 年 12 月
 
1 层体系架构模式
2 层架构模式在J2EE中的应用
3 Petstore的层架构模式
4 相关设计模式
5 总结
参考资料
关于作者
对于本文的评价
 
本文介绍了软件体系架构模式的层模式,分析了它的结构,特点,实现,以及优缺点等. 然后介绍遵循层模式的Architectural cube理论,结合J2EE的体系架构特点,剖析层模式是怎样应用的.最后以PetStore为例, 简单阐述怎样应用该模式在实际的J2EE系统之中.

1 层体系架构模式
层(layer)体系架构模式就是把应用系统分解成子任务组,其中每个子任务组处于一个特定的抽象层次上。

1.1 概述

层架构模式组织成一个层次结构,每一层为上层服务(Service Provider),同时也作为下层的客户端。在一些层次系统中,除了包含一些输出函数外,内部的层只对相邻的层可见。这样的系统中构件在一些层实现了虚拟机(在另一些层次系统中层是部分不透明的)机制。层的调用通过决定层间如何交互的协议来定义。这种风格支持基于可增加抽象层的设计。这样,允许将一个复杂问题分解成一个层堆栈的实现。由于每一层最多只影响两层,同时只要给相邻层提供接口,允许每层用不同的方法实现,因此为软件重用提供了强大的支持。

1.2 问题

层结构是最成熟的软件体系架构模式,它起源于早期的系统设计,由开始的函数调用,作为函数库,供其他程序进行调用. 一般在系统设计时,由一系列高层模块和底层模块处理构成,并且高层的模块依赖于底层.因此为了完成系统的设计必须要考虑一下因素:

  • 源码的修改会影响整个系统,应该被限定在一个部件内部而不影响其他模块
  • 接口应当稳定,甚至要被规范化
  • 系统的架构应该灵活,可以更换
  • 系统的开发需要被划分为多个部分,比如团队开发或者异地开发

1.3 模式结构

从系统高层的观点来看设计方案比较简单,它把系统进行分为几个层次并且把它们叠加起来,最下面的抽象层称为第一层,它是系统基础.依次类推,把n层放在第n-1层上.其结构如下图:

1.4 非软件描述

层模式在现实生活中很常见.特别在中国的封建社会的等级森严的制度下,把人分为几个等级,其实就是分层,上层可以指示下层.不过现在有的企业管理制度, 与这种管理理念相适应的管理体制是垂直的自上而下的泛官僚体制结构。其结构设置表现为自上而下的单向层级制,这种结构有利于政令的传达和执行,保证管理的效率,但是官僚特性也很明显.如下图:

层模式在现代物流也很常见,如下图的,在自行车在运输的过程,首先在自行车厂进行出厂,有人员进行打包,然后进行装运,最后再有相应的分销商,进行组装销售.

1.5 优点与缺点

层架构模式是最常用的一种软件体系架构模式。从它的实现和结构图中,我们可以得出,该模式具有以下优点和缺点:

1.5.1 优点

  • 层次的复用性.如果每个层次有很好的抽象接口,那么它可以被其他环境复用
  • 支持基于抽象程度递增的系统设计,使设计者可以把一个复杂系统按递增的步骤进行分解,使系统更容易模块化
  • 支持功能增强,因为每一层至多和相邻的上下层交互,因此功能的改变最多影响相邻的上下层
  • 可替换性.因为独立的层次设计很容易被功能相同的模块替换

但是在实际的项目中,该模式也有相应的不足

1.5.2 缺点

  • 低效率 分层结构通常要比单层结构的效率低.因为有时高层过分依赖底层的服务,因此必须穿过许多中间层进行数据的传送,甚至多次.
  • 改变行为的连锁反映

2 层架构模式在J2EE中的应用

2.1 J2EE层架构模式的背景

也许下图大家都比较熟悉,它介绍了软件从两层体系架构方式到三层的架构模式.

由于2层的架构方式,存在以下几点缺点:

  • 软件部署开销很大
    每个客户端数据库驱动都需要进行安装和设置,一但程序发生改变,就需要重新部署,这意味巨大的开销
  • 改变数据结构的开销很大
    客户端应用程序一般通过JDBC,ODBC,ADO等直接访问数据库,这表明客户程序直接与底层数据结构交互。如果改变数据结构来处理新的过程,就需要重新部署每个客户端。
  • 改变数据库的类型的开销很大
    由于客户端直接使用特定数据库的API,和特定的存输过程,触发器等,因此数据库类型的改变,会引起很多的修改。

但是通过把业务逻辑从存储过程和本地的业务逻辑进行分离,独立为一层,这样就是应用层架构模式最经典的应用之一.

2.2 J2ee应用的概述

J2EE平台为设计、开发、集成和部署企业应用提供基于组件的方法。这种方法不但能降低成本,还能对整个设计和实施过程进行快速跟踪。J2EE平台能提供多层分布式应用模型,能重用组件,能为用户提供统一安全模型和灵活的事务处理控制。在J2EE规范中进行了以下的分层:

  • 应用客户端组件
  • Servlets和Java Server Pages(JSP)组件(也称为Web组件)
  • Enterprise JavaBeans组件
  • 基础服务和与其他系统(如数据库等)的交互

2.3 Architecture and the Cube

软件体系架构研究者,把软件系统架构进行总结和分析,提出了Architecture cube理论.它把一个软件系统架构进行分解成三维进行分析,分别从Tier,layer,capabilities角度进行考虑.

其中Tiers定义为: A logical or physical organization of components into an ordered chain of service providers and consumers. Components within a tier typically consume the services of those in an "adjacent" provider tier and provide services to one or more "adjacent" consumer tiers. Within a tier, services are grouped to like requirements, such as functionality, security, or load distribution.

Layers定义为:The hardware and software stack that hosts services within a given tier. Physical, network, and software platforms and standard API sets support the components that provide a service. Layers, like tiers, represent a well-ordered relationship across boundaries that are mediated by interfaces. Whereas tiers represent processing chains across components, layers represent container/component relationships in implementation and deployment of services.

Systemic Qualities定义:The strategies, tools, and practices that deliver the requisite QoS (such as availability, scalability, security, and manageability) across the tiers and layers.

大家都知道,再考虑评价一个软件体系架构是否先进时,我们经常要从"非功能属性"的角度去评审.我们首先进行区分功能属性和非功能属性的区别.

功能属性(function property) 用来描述整个系统的功能特性(feature),并且通常与特定的功能需求相关.功能特性可以通过特定的功能使用户可以直接看到的应用功能,可以通过实现来进行描述.

非功能属性(non-function property) 定义为解决一个软件系统的可靠性,兼容性,性能,易用性,可维护性等.

我们的开发者过去习惯于专心提供功能属性,然而今天,非功能属性变得越来越来重要.

在实际系统架构上,可能是每一个Tier上由不同的layer组成, 或者说每一个layer都涉及不同的Tier,组成一个交错的系统, 并且Capabilities又和这两者交织,如下图:

2.4 J2EE架构的Cube

2.4.1 Tiers

2.4.1.1 概述

如果按照Cube理论把J2EE进行分析,从它的Ties层的角度进行考虑,把它分为以下几个Tiers:客户端层,表示层,业务逻辑,集成层,资源层.每层都是按系统中业务逻辑而划分的,它具有唯一的职责。每层与相邻层都是松散耦合的。还可以把整个系统表示为层的堆栈。

  • 客户端层
    该层代表访问系统的人员,应用程序,或系统的客户端。它是整个系统的对外接口,可以是Web浏览器(IE),Java应用程序(Swing),Java Applet,WAP,其他设备或者是批处理程序。
  • 表示层
    该层封装了用来服务访问本系统的所有客户端的表示层逻辑。该层解释客户端的请求,提供单次登录,实现会话管理,控制对业务的访问(权限检查),构造客户端的回复(response),以及把回复传递给客户端。一般Sevlet,JSP驻留在该层。
  • 业务逻辑层
    该层提供业务服务,包括业务数据和业务逻辑。通常应用程序的大多数业务处理集中在本层。同时它管理事务。EJB驻留在该层。
  • 集成层
    该层负责与外部系统和外部资源通信,它有多种方式,如与数据库连接使用的JDBC等.
  • 资源层
    该层包括业务数据源和外部系统资源,如Oracle数据库,JMS server,其他遗留系统等.

2.4.1.2 实现

在实现上面的Tier时一般我还需要结合实际情况进行分解, 如果大家对<J2EE core patterns>熟悉,可以了解到web层我们使用MVC模式,当然结合Filter,FrontControl,ViewHelp等模式,客户一般访问JSP(为了进行表示和业务的分离大多使用Taglib),然后由Control层进行处理,如果需要进行复杂的业务逻辑处理并且已经有后台实现(如EJB等),推荐经过Business Delegate层,访问后端业务逻辑(BP),一般业务逻辑使用Fa?ade模式进行封装成统一的接口,业务逻辑层实现复杂的事务处理,如果需要访问资源层,再经过DAO层访问资源(目前多数是RDBMS,有时是遗留系统如Coraba,JMS,WebService,SAP等).具体见下图:

关于Intercepting Filter,Front Controller,View Helper, Business Delegate,Fa?ade模式请参见<Core J2EE Pattern>。

2.4.2 Layers

2.4.2.1 概述

在开发J2EE应用时,我们一般把它纵向分为以下几个层,最下层为OS,JVM,network,层,它们负责系统的底层操作和网络数据的传输,一般我们开发人员不用关心运行在什么具体操作系统上,什么样的网络环境下.它的上层为J2EE服务层,一般由J2EE服务器(如WebSphere,WebLogic等)提供各种基础服务,如事务的管理(JTS),命名目录服务(JNDI),负载均衡(Load Balancing),容错(failover),安全(security)等,其次是通用业务层,它一般完成与具体业务无关的基本操作,包括如基础的框架(Framework),commons组件,如通用的数据库处理组件,系统错误处理组件,字符处理和数值处理组件,日志(log)处理,数据转化和编码维护等核心层.最上层才是我们的具体业务逻辑模块,它完成具体的业务逻辑.具体见下图:

2.4.2.2 实现

结合J2EE实际环境,最底层一般不需开发人员关心的操作系统和网络环境,并且不同J2EE服务厂商都提供了相应J2EE所必须得基础服务层,我们开发人员一般只需关心上面两层的实现,应用服务层经常使用类似于struts,webwork,waf等的web application framework,log服务一般选择log4j.commons log等,其他具体的数据处理,数据的转化等操作我们需要进行开发,不过这些一般与具体项目无关,可以在公司内部不同的项目之间共享.其实Jakarta Commons提供的功能一般可以使用在该层. 最上层才是我们的具体业务模块.见下图:

2.5 层模式实现讨论

  1. 为把任务分组成层而定义抽象准则。
  2. 根据抽象准则定义抽象层数。
  3. 给每个层命名并指定它们的任务。
  4. 指定服务
  5. 细化分层
  6. 为每个层指定一个接口。
  7. 构建独立层。
  8. 指定相邻层间的通信(或者调用)

3 Petstore的层架构模式
3.1 PetStore概述

PetStore是Sun公司在J2EE平台上开发的一个应用样例,是Java软件在J2EE的蓝图程序,它示范了如何利用J2EE1.3平台的性能去开发灵活、可升级的分布式平台企业应用系统。PetStore是一个运行在Web上的,为网络客户提供宠物信息浏览、网上订单和管理等功能的网上宠物店,在技术上使用了J2EE中的大部分企业组件和优秀的设计模式,提供了一套有高灵活性扩展性和可升级的完善J2EE开发框架.

PetStore共有4个子系统组成:

  • petstore Web Site 该部分是petstore中的核心,客户登录系统进行选择,定购,提交定单等。
  • petstore admin 该部分是系统的管理功能
  • Order processing center 定单调度中心,对客户提交的定单进行处理
  • PetStore supplier 为产品供应者提供的维护画面

在这里主要以WebSite为主进行分析(以下petstore均指该子系统),它是怎样进行分层处理的.

3.2 Petstore体系架构

我们按照层的架构模式进行分析,主要从Tiers和layer角度进行考虑.

3.2.1 Layer层

3.2.1.1 概述

PetStore是基于Web应用系统,它的客户端使用Broswer,然后是Web层的应用,业逻辑的层(由EJB实现),资源管理层(包括数据库,JMS,JavaMail等). 具体又细分为以下几层.

  • 客户请求浏览页面,一般Web层的View由JSP组成,并且使用了大量Taglib
  • 把每个请求映射到某个HTMLAction类,来响应它.HTML Action类是一个标准的类, 执行选择的HTML Action
  • WCC 是由WebClientController完成(实现类为WebClientControllerImpl),它实际是SUN核心模式的Business Delegate层
  • ECC 是EJBClientController,它实际是核心模式Session Fa?ade
  • EjbAction层执行EJB Action,传送event参数进来.EJB Action读event里面的参数,并且操纵EJB或者别的数据源来执行相应的商业操作.
  • 业务集成层,由通过DAO,EntityBean,JMS等访问相应的资源.

具体的详细的结构如下:

3.2.1.2 实现

在Web层它应用了著名的MVC模式,V由JSP来实现,为了业务逻辑和表示的分离,一般结合JSPTagLib. 它把请求提交到相应的处理MainServelet,然后准发到RequestProcessor,他根据读取mappings.xml,的配置信息,生成相应的处理类Action如

 

<url-mapping url="createuser.do" screen="create_customer.screen" isAction="true">
     <action-class>com.sun.j2ee.blueprints.petstore.controller.web.actions.CreateUserHTMLAction</action-class>
   </url-mapping>

每个Action一般包括以下几种方法(doStart, perform, doEnd),如果perform只需对请求的处理,如果处理的结果不需调用EJB的业务逻辑,只需返回即可,否则把请求组织成相应的Event,通过WCC转发到后台的业务逻辑层.代码见下:

 

public void processRequest(HttpServletRequest request) throws HTMLActionException, EventException, ServletException {
        Event ev = null;
        String fullURL = request.getRequestURI();
        // get the screen name
        String selectedURL = null;
        ServiceLocator sl = (ServiceLocator)request.getSession().getAttribute(WebKeys.SERVICE_LOCATOR);
        WebClientController wcc =  sl.getWebClientController();

       HTMLAction action = getAction(selectedURL);
       if (action != null) {
           action.setServletContext(context);
           action.doStart(request);
           ev = action.perform(request);
           EventResponse eventResponse = null;
           if (ev != null) {
               eventResponse  = wcc.handleEvent(ev);
           }
           action.doEnd(request, eventResponse);
        }
    }

通过WCC把Event转发到EC,这里WC是delegeteBussiness层

 

public class WebClientControllerImpl implements WebClientController {
    public synchronized EventResponse handleEvent(Event ev)
        throws EventException {
            return ccEjb.processEvent(ev);
    }
}
EC是Fa?ade层,如下,
public class EJBClientControllerEJB implements SessionBean {
protected StateMachine sm;
    public EventResponse processEvent(Event ev)
        throws EventException {
          return (sm.processEvent(ev));
}
}

然后根据相应的Event的类型使用不同EJBAction来完成相应的业务逻辑,

 

   public EventResponse processEvent(Event ev) throws EventException {
        String eventName = ev.getEventName();
        String actionName = null;
        EventResponse response = null;
        if (eventName != null) {
            actionName = getActionName(eventName);
            EJBAction action = null;
            action = (EJBAction)Class.forName(actionName).newInstance();
            if (action != null) {
                action.init(this);
                // do the magic
                action.doStart();
                response = action.perform(ev);
                action.doEnd();
            }
        }
        return response;
    }

每个具体的EJBAction完成自己的具体的业物逻辑,如果处理数据对象,则使用的相应的实体对象(data module).具体的层次调用过程,见下图:

3.2.2 Tier层

3.2.2.1 概述

PetStore Layer的设计分为以下几层,最底层为操作系统和网络服务,然后是基于J2EE服务器提供的系统服务层,上面是framework,Component层,包括WebApplicationFrameWork,以及commons业务逻辑,工具类等组成. 最上层才是具体的业务实现模块具体见下图:

3.2.2.2 实现

Petstore主要开发了两层,其中业务核心层,主要有几部分

  • WAF (Web Application Framework)
  • ApplicationControl 和Presentation (主要指JSP TagLib)
  • Components(如各种实体对象如customer,Account,等)
  • Business Logic Data各种常用的工具类

层的业务逻辑包括以下几个部分:

登录和注册,购物车模块,登录模块等

我们以WAF为例介绍业务共同层的作用, 开发者,可以基于这个框架,添加自己的代码和实现,下面红框内为WAF核心,如果增加新的业务功能只需增加相应的绿色部分.

同时其他的components提供了对JMS,Mail等的处理.

4 相关设计模式

4.1 外观模式(Facade)

外观模式的意图就是为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

其实层模式的每层之间的经常使用Fa?ade来进行封装成一致的接口供上层进行调用.如PetStore的EJB层的ECC就是Fa?ade模式的应用.

 

public interface EJBClientController extends javax.ejb.EJBObject {
    public EventResponse processEvent(Event ev) throws EventException, RemoteException;
}

J2EE核心模式的SessionFacade 模式定义了一类高层的业务组件,用于封装并集中较低层次业务组件之间的复杂交互。它为客户端提供单一接口,用于访问应用程序或应用程序子集的功能。它还把较低层次的业务组件彼此分离开来,从而使设计更具灵活性和可理解性。通过远程接口的细粒度访问是不可取的,因为这会增加网络通信量和滞后时间。多个细粒度调用会产生许多网络通信,而且会降低性能,因为远程调用的滞后时间很高。引入Session Facade会减少网络通信和滞后时间,因为对细粒度业务对象的所有访问都是本地的。见下图:

4.2 中介模式 (Mediator)

外观模式的意图就是用一个中介对象来封装一系列的对象交互。中介模式使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。在层架构模式中有时会使用该设计模式,使层之间的通信仅知道中介者并且只与通信,而不是层直接调用其他系统.使用中介模式如下:

5 总结
本文介绍了软件体系架构模式的层模式,分析了它的结构,特点,实现,以及优缺点.然后介绍遵循层模式的Architectural cube理论,结合J2EE的体系架构特点,剖析层模式是怎样应用的.最后以PetStore为例, 简单阐述怎样应用该模式在实际J2EE系统之中.

参考资料

  • 面向模式的软件体系结构 卷1:模式系统
    Pattern-Oriented Software Architecture, Volume 1: A System of Patterns
    作者: Frank Buschmann,Regine meunier,Hans Rohnert,Peter Sommerlad,Michael Stal

  • 软件体系结构的原理,组成与应用 万建成 卢雷

  • Take a 3-D Approach to Architecture Design SUN JOURNAL Volume 5 No. 1

  • Java Pet Store Sample Application http://java.sun.com/blueprints/code/index.html

  • Core J2EE Patterns:Best Practices and Design Strategies Deepak Alur

  • 设计模式:可复用面向对象软件的基础 Erich Gamma 等

 

关于作者
刘兵,某软件公司技术顾问,有5年多的J2EE软件开发经验和多年的项目管理实践经验.目前研究兴趣在J2EE,OOA/D,设计模式,软件体系架构等.可以通过 cnj2ee@tom.com 与他联系.

版权所有:UML软件工程组织