J2EE多层应用体系

 本文比较全面地介绍了与J2EE应用开发有关的各种基本概念,包括多层应用体系、容器、各种组件及其适用场合、J2EE基础服务、J2EE客户端类型等。

J2EE多层应用体系

J2EE可以理解为一个企业级的中间件体系或平台,它把多种分散到网络上的资源和应用连接起来,为构造和管理、运行可伸缩的企业级业务应用提供了一系列的应用组件和一个运行环境。从物理上看,J2EE环境可分布驻留到一个以上的服务器,单一的业务应用能够以一组分布式组件的形式部署到网络上的一个或者多个服务器。

要理解J2EE,就必须掌握下面几个支撑起J2EE体系的核心概念:

· J2EE n-tier应用体系:或称为J2EE多层应用体系,J2EE平台提供的基本应用架构。

· J2EE应用组件:构造J2EE应用的基本软件单元。

· J2EE企业服务:可被J2EE应用组件调用的公共服务功能。

· J2EE容器:J2EE组件的运行环境。

J2EE中间件体系定义了四个独立的层,应用软件就构造在这个框架上,它们是:

· 客户层(Client tier)。

· 表现逻辑层(Presentation logic tier)。

· 业务逻辑层(Business logic tier)。

· 企业信息系统层(EIS,Enterprise information systems tier)。

如图一所示:

表现逻辑层和业务逻辑层属于应用服务器领域。所谓应用服务器,也即J2EE平台的具体实现。这四层中的每一层都可以在物理上分布到多个机器,即使同属于应用服务器领域的表现逻辑层和业务逻辑层,也可以驻留在不同的应用服务器上。例如,在一个应用中,HTTP和表现逻辑的容器可以使用Sun公司的J2EE应用服务器iPlanet,部署业务逻辑组件可以用BEA公司的J2EE应用服务器Weblogic。

按照习惯,表现逻辑层总是与JSP容器相关,业务逻辑层总是与EJB容器相关。为便于理解,可以把J2EE多层体系中的“层”理解为一种概念实体,引入“层”这个概念是为了简化设计;与此相对,把容器理解为一种物理性的软件实体,容器的目标是为应用组件提供运行环境。

不同层次的J2EE应用组件驻留在它们各自的运行环境中,这些运行环境就是J2EE术语所谓的容器。容器是遵从一定接口标准的产品,为J2EE组件提供了必需的底层基础功能。按照J2EE标准编写好应用组件之后,还要用厂商专有的部署工具把它们分别部署到各自的容器。J2EE标准定义了四种不同的容器:

· Applet容器:运行和管理Applet。

· 应用客户端容器:运行和管理标准Java应用客户程序,包括Swing应用。

· Web容器:运行和管理表现逻辑层的Servlet和JSP组件。

· EJB容器:运行和管理业务逻辑层的EJB。

为了提供静态HTML页面服务,随同Web容器提供一个HTTP Web服务器是很典型的做法,目前几乎所有流行的J2EE应用服务器都有内建的HTTP Web服务器。

一般地,容器提供的基础功能包括内存管理、线程/同步机制、垃圾收集、可用性、可伸缩性、负载平衡和故障转移等。容器必须实现的基本接口和功能由J2EE规范定义,但具体如何实现完全由容器厂商自己决定。因此,J2EE既确保了不同应用服务器之间的兼容性,又为各个厂商的专有代码留下了自由空间。实际上,在中间件产业,各路厂商之所以得以施展各自神通,容器功不可没。

J2EE多层体系的思想在很大程度上受到了MVC设计模式的启发和影响。所谓MVC,即Model-View-Controller,它是一种在复杂的应用系统中划分和界定各个组件的职能和作用范围的设计模式。在MVC设计模式中,Model即模型,是处理核心数据模型或实现核心应用功能的部分;View即视图,主要与用户界面有关,例如把处理结果提供给客户端或其他应用。MVC设计模式认为这些不同的部分应该尽可能地相互独立,它们之间的交互则由Controller(控制器)协调。

例如,考虑一个在Internet上传输银行帐户信息的过程。按照MVC的设计思想,这个过程可以分割成四个独立的任务:

· 任务1:从浏览器启动传输过程(View)。

· 任务2:发出对帐户传输操作的调用(Controller)。

· 任务3:实际完成帐户传输操作(业务过程或Model)。

· 任务4:把传输状态(成功或失败)显示给浏览器(View)。

MVC认为核心业务过程(任务3)不应该做任何有关客户端的假设,例如,它不能假定客户端是一个浏览器,因为除了浏览器之外,其他的应用程序也应当能够顺利地调用核心业务过程;所有与客户端直接相关的操作应当由View来完成。至于业务逻辑和表现逻辑的联系和协调,则专门由Controller部分负责。

J2EE体系建立在MVC设计思想的基础上。很自然地,J2EE体系也鼓励把业务逻辑从表现层分离出来,属于Controller性质的代码可以放在这两个层的任意一个(或全部)。依赖于这种设计思想,J2EE为重用业务逻辑组件打开了广阔的空间。

 

J2EE应用组件

J2EE标准定义了一个完善的应用组件框架,作为企业应用系统基本构造模块的组件就建立在这个框架之上。几乎所有的业务应用,从简单的Web门户到复杂的企业级分布式事务应用,都可以在此基础上构造。

J2EE组件框架只是一个以库、类和接口形式提供的基础架构,最终构成应用的业务逻辑和表现/控制逻辑要由建立在这个框架上的应用组件实现。以J2EE提供的标准应用组件Servlet为例,为具体的业务应用构造的Servlet总是建立在J2EE提供的基本Servlet接口之上,开发者可以调用各种Servlet包提供的基本库和服务。许多系统级的服务都已经在这些库中提供,例如操作HTTP输入流读取数据和写入数据,只需直接调用即可。因此,我们把J2EE提供的组件基础架构叫做应用框架(Application Framework),把建立在应用框架之上的代码叫做J2EE应用组件(Application Component)。

如图一所示,无论是客户层、表现层还是业务逻辑层,都有相应的J2EE应用组件:

· 客户层:Applet,Javabean

· 表现逻辑层:Servlet,JSP,Javabean

· 业务逻辑层:EJB

必须指出的是,除了上述J2EE组件之外,标准的Java类和Jar包也可以在所有这些层上很好地运行。在许多场合,我们可以找到代码以普通Java类而不是J2EE组件状态存在的情形。EIS即Enterprise Information System,它包含所有的企业后端资源,例如数据库等。显然,对于EIS资源,我们要做的只是从组件访问它们,访问细节则由J2EE企业服务解决,所以在EIS层没有应用组件的位置。开发J2EE应用就是开发一种或者多种上述组件,然后把它们部署到各自的容器。

组件的接口确保组件遵从一定的标准并向外界提供公用功能,从而为具有良好互操作性的J2EE环境提供了基础。应用组件在各个层之间宽松结合,确保了组件互操作的灵活性和组件的可重用性。对于给定的业务情形,适当地选用和搭配各种应用组件是J2EE应用体系设计中一项富有艺术性的工作。由于组件的种类繁多,要想得到优质的代码和表现出色的应用,就要有丰富的知识和经验来确定组件的最佳搭配方案。对于每一种应用组件,J2EE明确定义了它在应用中应当担负的角色,从而为合理设计应用体系提供了坚实的基础。下面我们就来看看在应用服务器领域,各种组件的主要特点,请参见图二。

· Web容器和EJB容器是不同的,两者相对独立,可以是来自不同厂商的产品。这两种容器都可以使用企业服务。也就是说,无论是Web容器的组件还是EJB,都可以访问数据库连接、email服务、目录服务和消息服务。组件只能通过一个或者多个以驱动程序或适配器形式实现的企业服务访问EIS资源。

· 最好把所有应用组件频繁调用的用户自定义服务和库集中到一个独立的层。在图二的J2EE模型中,用户自定义的服务和库被合并到“自定义组件库”。这些库由用户自己开发,不属于标准J2EE应用服务器的一部分,一般它们会随着软件项目的成熟而日渐丰富。例如,配置文件工具库就是一个很好的例子:它根据指定的配置文件名字,打开该文件,然后以整数或字符串的形式返回指定的配置选项。

· 另一种常见的现象是,开发者在J2EE提供的核心企业服务的基础上编写自定义的访问例程。把这些自定义的服务访问例程组织成一个单独的“服务访问库”层是值得的。例如,假设我们在一个项目中用IBM的MQ Series作为消息系统。通常,我们会编写一些在JMS基础上访问MQ Series服务的简单API,例如给所有外发的消息加上企业标准的消息头。这时,最好把这些服务整理成“服务访问库”层的公用API,并让它们可被企业平台的所有应用调用。简而言之,服务访问库提供了J2EE API上的一层抽象,它们总是与特定的企业应用平台密切相关。

如前所述,在复杂的企业计算环境中,不同的J2EE组件应当担负不同的角色。下面我们就来看看具体情况。

Web容器组件:

· Servlet

Servlet是服务器端面向表现逻辑的组件,驻留在Web容器内。正如Applet扩展了浏览器的功能,Servlet扩展了Web服务器的功能——除了提供静态HTML之外,Servlet还提供编程和生成动态内容的功能。

Servlet能够处理来自客户端浏览器的请求,处理输入参数,把处理结果以HTTP应答的形式发送到客户端浏览器上显示出来。例如,Servlet可用来开发基于Web的简单认证系统,从客户端浏览器接收用户名字和密码,处理请求,再发回认证通过或不通过的应答。

除了接受来自客户端浏览器的请求之外,Servlet还能够响应其他Servlet的调用。虽然Servlet本身也能够生成发送给客户端的HTTP应答流,但是,就显示处理结果来说,JSP更擅长一些。

· JSP

JSP即Java Server Pages,它也是面向表现逻辑的组件,与Servlet一样,驻留在Web容器之内。但无论在适用场合还是功能方面,JSP与Servlet都有所不同。JSP页面是HTML和Java的混合物,即,JSP页面既能够包含HTML代码,也能够包含Java代码。JSP页面中的HTML代码被直接发送给客户端浏览器,而Java则被抽取出来由服务器处理。因此,JSP最适合于为HTML标签引入程序逻辑。

在JSP页面中,有一种结构化的、可重用的引用Java代码逻辑的途径,即使用JSP标记库。JSP标记库开发方便,能够更清楚地隔离Java代码和HTML代码。

JSP是对Servlet的补充和完善,经常用来显示Servlet的处理结果。但是,在一些应用设计中,只使用JSP(并充分有效地结合运用Javabean)而不使用Servlet的情形也很常见。

· Javabean

Javabean是基本的数据模型组件,在J2EE出现很久之前就已经被引入。在J2EE体系中,Javabean常常驻留在客户端或表现逻辑层,作为对Applet或JSP的补充。Javabean规范定义了Java代码如要成为Bean组件必须符合的条件。例如,一个简单的Java类如果定义了几个变量,并为这些变量定义了get_attribute()方法和set_attribute()方法,就可以认为是标准的Javabean组件。

Javabean与EJB除了名称相似之外,没有任何其他相似之处。EJB是一种完全不同的企业级Java应用组件。

EJB容器组件:

EJB是分布式可伸缩的业务逻辑组件,它们封装了企业Java工程的核心业务逻辑和数据模型元素。EJB驻留在称为EJB容器的特殊环境之内,EJB容器由应用服务器提供。J2EE规范定义了开发者编写的应用EJB与容器环境的关系(contract)。

开发EJB必须符合一定的接口要求,这些接口中的一部分方法由开发者实现,一部分由EJB容器提供者(或应用服务器厂商)实现。从某个方面来看,我们可以把EJB的这种接口要求看成一种隔离业务逻辑实现(开发者编写的方法)与应用基础结构(容器实现的方法)的途径。

EJB组件可以与任意其他EJB交互——不管对方是位于同一个容器之内,还是位于一个远程服务器的不同容器之内。EJB不仅可以调用所有的企业服务,还可以调用所有的自定义组件库和服务访问库。

针对不同的应用情况,EJB规范定义了几种不同的EJB类型,包括:无状态会话Bean、有状态会话Bean、实体Bean、消息驱动的Bean。

结合运用EJB、 Servlet和JSP,可构造出一个具有高度灵活性和可重用性的符合MVC特征的应用体系。

 

J2EE企业服务

J2EE环境以企业服务的形式提供了支撑企业应用的各种基石,例如邮件、数据库连接、消息和事务处理等。这些最基本的服务以接口、类库、驱动程序、适配器等形式提供。就像一个操作系统一样,J2EE提供了在各种服务之上的一个公共的Java接口。各个底层服务的实现细节不尽相同,可能存在细微的差别,公共的Java接口使得应用的代码完全脱离了细节问题的纠缠。

Web容器和EJB容器之内的应用组件通过调用J2EE企业服务,来访问企业系统内可用的资源和服务。这类资源和服务的范围相当广泛,从简单的数据库访问到通过消息/CICS环境执行的大型主机访问,应有尽有。

J2EE服务API在厂商私有的服务之上提供了一层标准化的Java接口,例如数据库连接和目录访问等,从应用的角度来看,有效地隐藏了与实现有关的细节。因此,应用开发者只需考虑标准的API集,无需依赖于面向具体资源、厂商的API,从而方便了在多种不同的服务实现之间迁移。例如,从一个J2EE应用组件的角度来看,访问Sybase数据库和Oracle数据库的方式非常相似,只要按照数据库类型改用相应的JDBC驱动程序和访问数据库的URL即可。也就是说,程序员根本不必进行任何代码级的修改工作,就能够方便地访问不同的数据库。

JDBC

JDBC即Java DataBase Connectivity。通过JDBC API能够访问范围广泛的关系数据库系统。JDBC API为所有公共的数据库功能提供了一组标准化的接口,J2EE组件利用这组接口查询和更新数据库。这些接口的具体实现则由JDBC驱动程序负责。

因此,应用程序的代码不牵涉到与具体数据库类型有关的调用,从一种数据库切换到另一种数据库通常可以很方便地完成。

JNDI

在分布式环境中,要寻找和识别分散到整个网络上的各种资源,就要用到名称和目录服务。网络上的各种资源用唯一的名字绑定到分布式的分层树形目录结构中,客户程序通过访问目录服务获取一个指向目标资源的句柄。

JNDI(Java Naming and Directory Interface)建立了访问企业级名称和目录服务的标准,它在LDAP、Novell Directory Service和Active Directory Service等具体的目录服务之上,建立了一个标准的服务层,使得J2EE组件能够以一种一致的、标准的形式访问各种底层的目录服务。

JMS

在异种系统的集成中,例如把大型主机系统和其他传统系统连接到J2EE中间件组件,消息服务扮演着至关重要的角色。在这些截然不同的异构系统之间,建立通信链的关键就在于通信双方分别安装一个消息服务进程。应用软件与消息服务进程交互,消息服务进程再以点对点或异步的形式通过网络把消息传递给其他消息服务进程。

JMS(Java Messaging Service)在诸如IBM的MQ Series、Microsoft的MSMQ和TIBCO的Rendezvous之类的消息服务系统之上,建立了调用标准,即在这些私有的消息API调用之上定义了一个标准服务层,使得J2EE应用不再被绑定到实际执行消息服务的私有实现上。

Javamail/JAF

顾名思义,Javamail API是为J2EE组件提供e-mail服务的。它在具体的邮件服务实现(例如SMTP和POP3)之上,统一对各种可能用到的公共服务的访问形式,例如邮件格式、发送/接收邮件、附件处理等。

JavaMail 要求 Java 激活框架(JAF,Javabean Activation Framework)来处理复杂的数据类型,例如MIME。

RMI-IIOP/Java IDL

这两种技术支持J2EE组件和CORBA组件的相互通信。CORBA即Common Object Request Broker Architecture的缩写,是OMG(对象管理组织)定义的一种著名的分布式应用框架,已经有多年历史。

Java IDL是从J2EE环境访问现有CORBA对象的推荐方法,但RMI-IIOP也能够将J2EE组件提供给CORBA客户程序。

JAX

JAX即Java API for XML,是一种简化J2EE领域内XML文档使用的Java XML API。JAX API提供的服务包括XML解析(包括SAX和DOM)、XML与Java对象的绑定、XML消息和XSLT转换。JAX API是以Web服务的形式提供J2EE业务逻辑组件的基础,也是调用其他各种不同环境提供的Web服务的基础。

JCA

JCA即Java Connector Architecture(Java连接器体系),支持J2EE中间件与现有企业信息系统的无缝集成,例如ERP、主机系统、事务处理系统、数据库以及其他传统应用系统等。就像其他服务API一样,JCA为各个厂商提供了开发资源适配器的空间,由资源适配器与J2EE应用服务器建立系统级连接协议,与访问EIS资源的应用组件建立应用级连接协议。

 

J2EE客户端

对于J2EE环境,客户访问的类型可总结如下:

访问EJB中的业务逻辑服务:这也许是所有J2EE环境中最常见的客户访问形式。如果核心的业务逻辑规则能够封装成宽松结合的EJB或其他Java组件,它们就可以在多个应用之内重用。有的企业甚至专门制定了构造J2EE组件和服务的长远规划(例如发展出全局性的业务逻辑知识库或公用的EIS访问网关),由富有经验的分析师负责精心设计和监管业务逻辑模块,确保最佳的可重用性和表现。例如,银行的资金转移服务把资金从一个帐户划转到另一个帐户,如果这个服务以EJB的形式实现,就可以供不同类型的客户端重用——例如银行的内勤服务系统、Web银行、移动银行,等等。

访问表现逻辑服务:表现逻辑服务与客户终端的类型关系密切,要在不同的应用之间重用一般比较困难。但是,利用某些技术和设计方法,可以把“表现的内容”与“表现的方式”分离开来。典型的方案是使用XML和XSLT,完全分离表现逻辑(XSLT)和内容(XML)。例如,考虑前述资金转移服务,假设现在要在成功执行该服务之后,发送一个回执和帐户余额信息。不论客户端是什么类型,要显示的数据都是一样的(即资金划拨是否成功,帐户余额),但具体的显示方式则因客户端的不同而不同,例如在Web页面上,可能要显示几幅装饰图形,但在移动设备上肯定要用另一种简化的显示方式。在这种场合,如果表现方式(图形、字体等的定义信息)在分开的XSLT页面中定义,例如web.xsl、mobile.xsl等,然后让表现方式和表现内容在服务器端或客户端以某一种方式结合,就可以成功实现两者分离的目标。

访问企业服务:有的时候,J2EE领域之外的组件可能需要访问J2EE平台的企业服务。如果在设计企业J2EE体系时考虑到了让外部应用和组件访问,这种需求必然会更加明确。例如,我们可以在J2EE企业email服务之上构造一个公共的网关,使得email服务不仅可被J2EE平台内部的组件调用,还可以被所有其他需要发送和接收email的企业应用调用。类似地,所有的数据库访问调用可以集中到J2EE环境之内。这种设计方案有助于改进对企业内各种基础服务的控制和协调、利用。

通过J2EE访问EIS服务:J2EE除了能够把它自身的应用组件提供给不同类型的客户之外,还能够作为一个中央控制器,支持对后端EIS资源的访问。如果后端的EIS系统庞大且复杂,或者有许多应用不能直接访问EIS资源,通过J2EE访问EIS服务更具有实用意义。例如,假设后端运行着Siebel CRM系统,客户通过消息系统和Siebel适配器访问该系统提供的资源。这时,就可以在J2EE内利用JMS、EJB等技术,构造一个访问网关,使得各种Java客户程序和其他应用能够以一种一致的方式访问Siebel资源。

能够调用J2EE服务的客户类型非常广泛。当然,实际可支持的客户类型依赖于企业应用系统的总体设计和构造。下面列出了其中一部分:

Web(HTML)客户端:通过HTTP协议访问J2EE服务的客户端。这是最常见的客户端类型,许多J2EE工程的最初阶段就是从Web门户的形式开始,所以J2EE应用服务器常常带有内建的HTTP Web服务器。通过HTTP协议将J2EE环境连接到Web/Internet的组件包括Servlet和JSP。Servlet最适合于接收客户的请求并调用适当的业务逻辑,JSP最适合于呈现处理结果。

· 设备客户端:利用J2ME、WAP等技术,通过手持设备和移动电话访问J2EE服务。

· Applet客户端:浏览器或Applet容器之内的Java Applet,能够直接访问J2EE业务逻辑环境。与普通HTML页面相比,Java Applet要强大得多,能够调用描述业务逻辑的Bean(直接调用EJB)。然而,把View和Controller的逻辑嵌入到Applet将使得Applet规模过大,除非有特别的原因,这种做法在实践中通常不可取。嵌入Applet的代码越多,偏离Model-View-Controller体系就越远,同时,客户端下载Applet并在浏览器JVM内运行它的时间开销也越大。在Applet内部,最好只执行一些客户端的验证工作,把其他所有处理工作转移到服务器端组件。

· 独立的Java应用客户端:和Applet一样,独立的Java应用客户端也能够直接访问业务逻辑组件。独立的Java应用客户端能够通过Java RMI调用访问所有的业务逻辑组件。EJB之间的相互通信通过RMI实现,所以独立的Java应用客户端可以直接执行基于RMI的远程过程调用。需要访问EJB时,Java客户端首先通过JNDI查询分布式目录服务,获得一个指定EJB的句柄;获得句柄之后,客户端就可以开始调用业务逻辑代码了。由于EJB是分布式组件,即使对于分布到不同J2EE服务器环境的不同EJB,访问形式也是一致的。

· 其他服务器上的EJB客户端:运行在其他J2EE服务器或容器上的业务逻辑组件(普通Java类或EJB)能够直接访问J2EE环境内的EJB。例如,如果一家企业和它的合作伙伴决定启用统一的J2EE中间件平台,它们就可以互相许可对方跨平台访问自己的业务逻辑组件。EJB有着优秀的验证和授权机制——包括方法级的安全机制,因而,在不同的平台之间相互交换EJB服务的同时,可以建立完善的访问控制体系。在这种场合,应当密切注意只有那些经过授权的EJB才能够访问指定的业务逻辑或服务。

· CORBA客户端:驻留在CORBA ORB环境内的CORBA应用客户端通过远程IIOP调用访问EJB。J2EE促进了与驻留在CORBA ORB之内的CORBA组件的全面交互。Java接口定义语言(Java IDL)能够把EJB描述成CORBA客户程序眼中的CORBA对象;与此对应,如果需要从EJB访问CORBA组件,则可以使用RMI-IIOP调用。

· 传统系统作为客户端(ERP/CRM/大型主机系统):诸如ERP/CRM和大型主机系统之类的传统系统也能够访问J2EE环境内的资源和服务。当传统系统作为客户端访问J2EE环境时,最常见的途径是通过消息系统。从这个意义上说,对于J2EE环境,作为客户端的传统系统可以看成是JMS客户端。如果传统系统提供了相应的连接器,Java连接器体系(JCA)可能很有用。

· JMS客户端:JMS客户端是通过一种或多种支持JMS的消息系统(如IBM MQ Series)访问J2EE的应用或组件。由于J2EE领域内与消息系统密切交互的需求很大,所以J2EE引入了一种新的EJB类型,即“消息驱动的Bean”(Message Driven Bean)。消息驱动的Bean支持与基于JMS的消息系统进行同步或异步的交互;对于其他消息应用访问EJB容器内的业务逻辑组件,也能够提供有效的支持。

· Windows客户端:用VB/VC ++等构造的Windows应用。在.NET框架出现之前,为了把EJB直接显露给Windows应用的本机调用,人们已经对Java客户服务(CAS)进行了一定的努力。但是,随着.NET的出现,重心已经稍微偏离了CAS。现在,人们把寻找这两种环境最佳交互途径的焦点转移到了厂商中立的标准和Web服务技术上。

· Web服务客户端:通过非厂商私有的技术,例如SOAP/WSDL和UDDI等,访问J2EE资源。最近,各种与Web服务有关的技术,诸如SOAP、UDDI以及WSDL等,在企业计算领域受到了广泛的认可和欢迎。任何组件或应用,只要它理解SOAP调用并把它的服务发布到UDDI之类的目录,就能够以Web服务的形式提供其服务。Java的XML API,例如JAXP(Java API for XML Processing)、JAXR((Java API for XML Registries)、JAXB(Java API for XML Binding)、JAXM(Java API for XML Messaging)以及JAX-RPC(Java API for XML-based Remote Procedural Call)等,推动了J2EE和Web服务这两个环境的全面交互。

综上所述,不同类型的客户都可以访问J2EE环境提供的各种服务。Java客户能够直接访问J2EE业务逻辑组件,而非Java的客户则必须通过企业消息服务或其他途径才能访问J2EE环境下的业务逻辑。然后,随着.NET的出现和Web服务的发展,Windows客户访问J2EE业务逻辑服务不再困难。

 

你可能感兴趣的:(ejb,servlet,java,应用服务器,applet,web服务)