
1.2 Java EE应用分层架构
对程序员来说很常见的一种情况是在没有合理的程序架构时就开始编程,没有一个清晰的和定义好的架构的时候,大多数开发者和架构师通常会使用标准式的传统分层架构模式(也被称为多层架构)——通过将源码模块分割为几个不同的层到不同的包中。不幸的是,这种编码方式会导致一系列没有组织性的代码模块,这些模块缺乏明确的规则、职责和同其他模块之间的关联。这通常被称为架构大泥球。
应用程序缺乏合理的架构一般会导致程序过度耦合、容易被破坏、难以应对变化,同时很难有一个清晰的版本或者方向性。这样的结果是,如果没有充分理解程序系统里每个组件和模块,就很难定义这个程序的结构特征,有关于程序的部署和维护的基本问题都难以回答,例如:程序架构是什么规模?应用程序有什么性能特点?应用程序有多容易应对变化?应用程序的部署特点是什么?架构是如何反应的?
好的架构模式能帮助程序员定义应用程序的基本特征和行为。例如,一些架构模式会让程序自然而然地朝着具有良好伸缩性的方向发展,而其他架构模式会让程序朝着高度灵活的方向发展。知道了这些特点,了解架构模式的优点和缺点是非常必要的,它能帮助程序员选择一个适合自己特定的业务需求和目标的程序。
1.2.1 分层模式概述
层(layer)体系架构模式就是把应用系统分解成子任务组,其中每个子任务组处于一个特定的抽象层次上。
1.层模式概述
层模式组织成一个层次结构,每一层为上层服务(Service Provider),同时也作为下层的客户端。在一些层次系统中,除了包含一些输出函数外,内部的层只对相邻的层可见。这样的系统中构件在一些层实现了虚拟机(在另一些层次系统中层是部分不透明的)机制。层的调用通过决定层间如何交互的协议来定义。这种风格支持基于可增加抽象层的设计。这样,允许将一个复杂问题分解成一个层堆栈的实现。由于每一层最多只影响两层,同时只要给相邻层提供接口,允许每层用不同的方法实现,因此为软件重用提供了强大的支持。
2.考虑的因素
层模式是最成熟的软件体系架构模式,起源于早期的系统设计,由开始的函数调用,作为函数库,供其他程序进行调用,一般在系统设计时,由一系列高层模块和底层模块处理构成,并且高层的模块依赖于底层。因此为了完成系统的设计必须要考虑以下因素:
❑ 源码的修改会影响整个系统,应该被限定在一个部件内部而不影响其他模块。
❑ 接口应当稳定,甚至应被规范化。
❑ 系统的架构应该灵活,可以更换。
❑ 系统的开发需要被划分为多个部分,如团队开发或者异地开发。
3.模式结构
从系统高层的观点来看设计方案比较简单,它把系统分为几个层次并且把它们叠加起来,最下面的抽象层称为第一层,是系统基础。依次类推,把n层放在第n-1层上,其结构如图1-3所示。

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

图1-4 官僚体制结构
层模式在现代物流也很常见,如图1-5所示,自行车在运输的过程中,首先在自行车厂进行出厂,由工作人员进行打包,再进行装运,最后通过相应的分销商,进行组装销售。

图1-5 自行车运输过程
5.优点与缺点
层模式是最常用的一种软件体系架构模式。从其实现和结构图中可以总结出该模式的优点和缺点如下。
❑ 层次的复用性。如果每个层次有很好的抽象接口,那么可以被其他环境复用。
❑ 支持基于抽象程度递增的系统设计。使设计者可以把一个复杂系统按递增的步骤进行分解,使系统更容易模块化。
❑ 支持功能增强。因为每一层至多和相邻的上下层交互,因此功能的改变最多影响相邻的上下层。
❑ 可替换性。因为独立的层次设计很容易被功能相同的模块替换但是在实际的项目中,该模式也有相应的不足缺点。
❑ 低效率。分层结构通常要比单层结构的效率低。因为有时高层过分依赖底层的服务,因此必须穿过许多中间层进行数据的传送,甚至多次改变行为的连锁反应。
1.2.2 Java EE的结构
1.J2EE层模式的背景
如图1-6所示的架构大家都比较熟悉,为软件从两层体系架构方式到三层的转变。

图1-6 两层架构模式到三层架构模式
由于两层的架构方式存在以下缺点:
❑ 软件部署开销很大。每个客户端数据库驱动都需要进行安装和设置,一旦程序发生改变就需要重新部署,这意味着巨大的开销。
❑ 改变数据结构的开销很大。客户端应用程序一般通过JDBC、ODBC、ADO等直接访问数据库,这表明客户程序直接与底层数据结构交互。如果改变数据结构来处理新的过程,就需要重新部署每个客户端。
❑ 改变数据库类型的开销很大。由于客户端直接使用特定数据库的API和特定的存输过程、触发器等,因此数据库类型的改变会引起很多的修改。
因而,可以通过把业务逻辑从存储过程和本地的业务逻辑分离出来,独立为一层,这样就是应用层架构模式最经典的三层架构(3-tier architecture)。
(1)表现层(Presentation layer,PL)
主要负责数据的输入接口和输出。输入指在Web、客户端或为外界提供的API的数据请求接口;输出则是Web界面、客户端输出、API的数据输出。页面模版、对外API数据格式化、Request接受、Output推送、Commander操作都在这一层。
(2)业务逻辑层(Business Logic Layer,BLL)
主要负责从原始数据到结果数据的中间过程。系统中最关键、最重要的一层。也被称作领域层(Domain Layer),领域中所有对象的逻辑关系和功能实现算法都在这一层中。业务逻辑、服务等处于这一层。
(3)数据访问层(Data Access Layer,DAL)
主要是对原始数据的操作层(CRUD操作),为业务逻辑层或表示层提供数据服务。数据源包括,数据库、文件、网络存储系统、其他系统开放的API、程序运行上下文环境等。许多框架中的ORM、Active Record、Dao类或库都处于这一层。
三层架构能较好地满足大部分的业务场景,实现高内聚、低耦合。不同层次之间逻辑解耦或者隔离,变为弱依赖,每层的逻辑内聚。从层次角度看,使系统有了较好的可扩展性。但三层架构也有以下不足:
业务逻辑复杂度高的系统,业务逻辑层将变得庞大臃肿,为了解决这个问题,四层架构/多层架构被人提出。不关注表现层实现的四层架构(4-tier architecture),和三层架构极为类似,分为表示层、服务层、业务逻辑层、数据访问层。除了服务层,其他三层和三层架构的三层几乎一致,而服务层是对三层架构中业务逻辑层的再细分,以解决业务逻辑层经常出现的臃肿问题。
四层架构是Java EE推荐的分层架构,尤其是Spring+Struts+Hibernate(SSH)组合的框架将Dao层、Service层做了明确的定义和规范。由于SSH框架被广泛使用,其他框架,包括其他语言的框架(如PHP)也都借鉴SSH,因此在这些框架里能看到Dao类、Service类的抽象定义。
在三层架构中,把业务逻辑层的上层逻辑分离出来,组成服务层(Service Layer)。服务层往往是逻辑的表示层,即向上层(表示层)提供逻辑的外观。事务控制、安全检查、事务脚本等可以置入业务层。四层架构是三层架构的发展或进化。服务层的出现让三层架构的业务逻辑层不再变得臃肿。同样再进一步细分就是五层架构了。
这样,Java EE应用架构大致上可分为如图1-7所示情况。

图1-7 Java EE应用架构
(1)Domain Object(领域对象)层
此层由系列的POJO(Plain Old Java Object,普通的、传统的Java对象)组成,这些对象是该系统的Domain Object,往往包含了各自所需要实现的业务逻辑方法。与业务逻辑层可同在一层。
(2)DAO(Data Access Object,数据访问对象)层
此层由系列的DAO组件组成,这些DAO实现了对数据库的创建、查询、更新和删除(CRUD)等原子操作。在经典Java EE应用中,DAO层也被改称为EAO层,EAO层组件的作用与DAO层组件的作用基本相似,只是EAO层主要完成对实体(Entity)的CRUD操作,因此简称为EAO层。
(3)业务逻辑层
此层由系列的业务逻辑对象组成,这些业务逻辑对象实现了系统所需要的业务逻辑方法。这些业务逻辑方法可能仅仅用于暴露Domain Object对象所实现的业务逻辑方法,也可能是依赖DAO组件实现的业务逻辑方法。
(4)MVC控制层
此层由系列控制器组成,这些控制器用于拦截用户请求,并调用业务逻辑组件的业务逻辑方法,处理用户请求,并根据处理结果转发到不同的表现层组件。
(5)表现层
此层由系列的JSP页面、Velocity页面、PDF文档视图组件组成。此层负责收集用户请求,并将显示处理结果。
以上各层的Java EE组件之间以松耦合的方式耦合在一起,各组件并不以硬编码方式耦合,这种方式是为了应用以后的扩展性。从上向下,上面组件的实现依赖于下面组件的功能;从下向上,下面组件支持上面组件的实现。
当然,四层架构和三层架构都存在一个不足,就是不强调前端的实现。当面对需要个性化定制界面、复杂用户交互、页面之间有依赖关系时,需要更好的解决方案。
另外,还有一种MVC模式,其主要包括三部分,Model-View-Controller(模型-视图-控制器)。相比于三层架构或者四层架构,MVC最突出的优点是前端控制的灵活性。如果MVC的两部分View和Controller剥离出来,实际上是一种叫前端控制器模式的设计模式。
MVC的缺点很明显,将前端以外逻辑都放到Model里,随着业务增多,Model将越来越难以维护。MVC并不适合称为一种分层架构,更适合称为一种复合的设计模式。有人还将MVC模式归类为前端架构。MVC模式最适合新闻门户网站、展示类网站,此类网站业务逻辑往往较为简单。MVC模式最适合产品初创时被使用,因为项目初期逻辑简单,使用MVC模式产品能快速成型,可以尽早投放市场进行试验(多数可能会被淘汰),这样就降低了试验成本。MVC模式最适合产品原型的实现(注重前端)。
总之,分层的选择要平衡成本和风险,使收益最大化。业务逻辑不要局限于四层架构或三层架构,依据领域业务特点可更细地划分层次。
2.J2EE分层应用概述
J2EE平台为设计、开发、集成和部署企业应用提供基于组件的方法。这种方法不但能降低成本,还能对整个设计和实施过程进行快速跟踪。J2EE平台能提供多层分布式应用模型,能重用组件,能为用户提供统一安全模型和灵活的事务处理控制。在J2EE规范中进行了以下的分层,不同的组件可以在逻辑上分为三层:后端层、中间层和网络层。这只是一个逻辑表示,根据应用程序的要求,组件可以被限制到不同的层。Java EE 7体系结构及其提供的主要服务如图1-8所示。

图1-8 Java EE 7体系结构
❑ JPA(Java Persistence API,Java持久化API)和JMS(Java Message Service,Java信息服务),JPA是在数据库中存储对象的ORM(Object/relational mapping,对象关系表)定义提供基本的服务,如数据库访问。JMS这个API保证服务器和应用在网络上的通信可靠、异步。如ActiveMQ实现了JMS。
❑ JCA(Java EE Connector Architecture,J2EE连接器架构)允许连接到原有系统,批量处理非交互、块状任务。通过此服务可以连接不同开发架构的应用程序。
❑ Managed beans和EJB(Enterprise Java Beans,企业级Java Beans)使用POJO基本服务,提供一种简化的编程模型。Managed Beans可以执行嵌入代码的Java对象。在Spring框架中,这是一些添加了@Autowired注释的对象。
❑ CDI(Contexts And Dependency Injection,上下文和依赖注入),提供适用于各种组件的概念拦截和注释,如类型安全的依赖注入,使用拦截器和一套共同的注释表示横切关注点。JTA事务拦截器实现,可以应用于任何POJO。
❑ CDI是Java EE整个下一代类型安全的依赖注入的事实上的API。在Spring框架中,应用程序可以设计应用的上下文,控制反转(IoC)和依赖注入功能(DI)CDI扩展允许以标准的方式超出现有能力来扩展平台。
❑ 应用客户端组件Servlets和Java Server Pages(JSP)组件(也称为Web组件),Enterprise JavaBeans组件。
❑ Web Services使用JAX-RS(定义REST含状态传输之类服务的API)、JAX-WS、JSF、JSP和EL定义编程模型的Web应用。Web Fragments允许以自然方式自动注册第三方Web框架。JSON提供了一种方法来解析和Web层的生成JSON结构。Web Socket可以通过一个TCP连接建立双向、全双工的通信信道。
❑ Bean Validation标准化了Java平台的约束定义、描述和验证,即使用注释的方式对Java Bean进行约束验证。
提示:
➢ 微软的.NET开发架构也是由Java EE而来。
➢ 著名的.NET架构在推出时,也大量参考了Java EE中各个组成部分,并提出了与之类似的企业开发架构。也就是两种架构之间相互学习、互相取长补短,为程序开发人员提供更多更好的程序开发支持。