如果您已经安装了J2EE TM Platform (Enterprise Edition )软件,并通读
了各种可用的指南来帮助您学习使用该软件,那么,您可能已经准备
开始为J2EE 平台编写第一个多层企业应用程序了。在这个时候,您可
能对应用设计应当在何处着手、以及如何判断哪些J2EE API 最能满足
您的要求上存有疑惑 。
您可以得到帮助。《为企业版Java TM 2 平台设计企业应用程序》(Designing Enterprise
Applications for the Java TM 2 Platform, Enterprise Edition ISBN 0-201-70277-0 描述了J2EE 平
台,并提出了一个编程模型,可以帮助您在为J2EE 平台设计多层企业应用程序时作出最佳
决策。为了理论联系实际,在这里举了一个电子商务宠物商店应用程序的例子,描述了该
编程模型是如何指导设计的。该书和该宠物商店应用程序一起被称作J2EE Blueprints (J2EE
蓝图)。
本文是J2EE 蓝图的一个摘要,向您介绍该编程模型,并帮助您掌握它。您可以访问J2EE
下载页面,下载该书的PostScript 或者PDF 格式的版本,或者下载书中作为例子的宠物商店
应用程序。该书印刷本将在2000 年7 月上市 。
˙J2EE 基本架构:概述(J2EE Architecture —A Bird's-Eye View )
˙可再用应用组件(Reusable Application Components )
˙设计用户界面和引擎(Designing the User Interface and Engine )
˙设计基于Web 的应用(Designing Web-Based Applications )
˙Servlets 和jsp 页面(Servlets and JSP Pages )
˙模型、视图、控制器设计范式(Model, View, Controller Design Pattern )
˙J2EE 应用中的Enterprise Beans (Enterprise Beans in J2EE Applications )
˙宠物商店应用程序(Pet Store Application )
J2EE 基本架构:概述基本架构:概述基本架构:概述基本架构:概 述
电子商务和信息技术的快速发展及对它的需求给应用程序开发人员
带来了新的压力。必须以比以前更少的金钱、更少的资源来更快地设
计、建立和生产企业应用程序 。
为了降低成本,并加快企业应用程序的设计和开发,J2EE 平台提供了一个基于组件的方法,
来设计、开发、装配及部署企业应用程序。J2EE 平台提供了多层的分布式的应用模型、组
件再用、一致化的安全模型以及灵活的事务控制。您不仅可以比以前更快的速度向市场推出
创造性的客户解决方案,而且,您的平台独立的、基于组件的J2EE 解决方案不会被束缚在2
任何一个厂商的产品和API 上 。
J2EE 规范定义了以下种类的组件 :
˙应用的客户组件(Application client components )
˙Enterprise JavaBeans TM 组件(Enterprise JavaBeans TM components )
˙Servlets 及JavaServer Pages TM (JSP 页面)组件(也被称作Web 组件)(Servlets and
JavaServer PagesTM (JSP pages) components )
˙Applets
一个多层的分布式的应用模型意味着应用逻辑被根据功能而划分成组件,并且可以在同一个
服务器或不同的服务器上安装组成J2EE 应用的这些不同的组件。一个应用组件应被安装在
什么地方,取决于该应用组件属于该多层的J2EE 环境中的哪一层。这些层是客户层、Web
层 、 业务层及企业信息系统层(EIS )。
客户层(客户层(客户层(客户层(Client Tier )))
J2EE 应用可以是基于Web 的,也可以是不基于Web 的。在一个基于
Web 的J2EE 应用中,用户的浏览器在客户层中运行,并从一个Web
服务器上下载WEB 层中的静态Html 页面或由JSP 或servlets 生成的
动态HTML 页面 。
在一个不基于Web 的J2EE 应用程序中,一个独立客户程序,或者不运行在一个HTML 页
面中,而是运行在其它一些基于网络的系统(比如手持设备或汽车电话)中的applet 程序,
在客户层中运行,并在不经过Web 层的情况下访问enterprise beans 。该不基于Web 的客户
层可能也包括一个JavaBeans 类来管理用户输入,并将该输入发送到在企业层中运行的
enterprise bean 类来处理。根据J2EE 规范,JavaBeans 类不被视为组件 。
为J2EE 平台编写的JavaBeans 类有实例变量和用于访问实例变量中的数据的“get 和set 方
法”。以此种方式使用的JavaBeans 类在设计和实现上通常都是简单的,但是它们必须符合
JavaBeans 规范中列出的命名和设计约定。
Web 层层层层
J2EE Web 组件可以由JSP 页面、基于Web 的applets 以及显示HTML 页面的servlets 组成。
调用servlets 或者JSP 页面的HTML 页面在应用程序组装时与Web 组件打包在一起。就像
客户层一样,Web 层可能包括一个JavaBeans 类来管理用户输入,并将输入发送到在业务层
中运行的enterprise beans 类来处理 。
运行在客户层的Web 组件依赖容器来支持诸如客户请求和响应及enterprise bean 查询等。
业务层业务层业务层业务 层
作为解决或满足某个特定业务领域(比如银行、零售或金融业)的需要的逻辑的业务代码由
运行在业务层的enterprise beans 来执行。一个enterprise bean 从客户程序处接收数据,对数
据进行处理(如果需要),再将数据发送到企业信息系统层存储。一个enterprise bean 还从
存储中检索数据,并将数据送回客户程序 。3
运行在业务层的enterprise beans 依赖于容器来为诸如事务、生命期、状态管理、多线程及资
源存储池提供通常都非常复杂的系统级代码。
业务层经常被称作Enterprise JavaBeans (EJB )层 。业务层和Web 层一起构成了3 层J2EE
应用的中间层, 而其它两层是客户层和企业信息系统层.
企业信息系统层企业信息系统层企业信息系统层企业信息系统层
企业信息系统层运行企业信息系统软件,这层包括企业基础设施系统,
例如企业资源计划(ERP )、大型机事务处理(mainframe transaction
processing )、数据库系统及其他遗留信息系统(legacy information
systems )。J2EE 应用组件因为某种原因( 例如访问数据库) 可能需要访
问企业信息系统。
注意:注意:注意:注意:J2EE 平台的未来版本将支持Connector 架构,该架构是将J2EE 平台连接到企业信息
系统上的一个标准API 。
查询服务(查询服务(查询服务(查询服务(lookup services )))
因为一个J2EE 应用程序的组件是单独运行的,并且往往在不同的设备上运行,因此,需要
一种能让客户层和Web 层代码查询并引用其他代码和资源的方法。客户层和Web 层代码使
用Java 命名和目录接口(JNDI )来查询用户定义的对象(例如enterprise beans )、环境条目
(例如一个数据库驱动器的位置)、企业信息系统层中用于查找资源的JDBC TM DataSource
对象,以及消息连接。
安全和事务管理(安全和事务管理(安全和事务管理(安全和事务管理(Security and Transaction Management )))
诸如安全和事务管理这样的应用行为可以在部署时在Web 和enterprise bean 组件上进行配
置。这个特征将应用逻辑从可能随装配而变化的配置设定中分开了 。
安全安全安全安 全
J2EE 安全模型允许配置一个Web 或enterprise bean 组件,使系统资源
只能由授权的用户访问。例如,一个Web 组件可以被配置成提示输入
用户名和密码。一个enterprise bean 组件可以被配置成只让特定团体
中的成员调用其某些方法。或者,一个servlet 组件可以被配置成让某
个组织中的所有人都能访问其某些方法,同时只让该组织中的某些享
有特权的人访问一些方法。同样是该servlet 组件,可以针对另外一个环境而被配置成让每
个人都能访问其所有方法,或者仅让选定的少数人访问其所有方法 。
事务管理(事务管理(事务管理(事务管理(Transaction Management )))
J2EE 事务模型使得能够在部署时定义构成一个单一事务的方法之间的关系,以使一个事务
中的所有方法被处理成一个单一的单元。这是我们所希望的,因为一个事务是一系列步骤,
这些步骤要么全部完成,要么全部取消。
例如,一个enterprise bean 可能有一组方法,使我们可以通过从第一个账户借出并存入第二
个账户的方式而将钱从第一个账户转移到第二个账户。我们希望全部的操作被作为一个单元
对待,这样,如果在借出之后存入之前发生了故障,该借出操作被取消。4
事务属性是在装配期间定义在一个组件上的。这使得能将来自多个应用组件的方法归到一个
事务中,这说明,我们可以轻易变更一个J2EE 应用程序中的应用组件,并重新指定事务属
性,而不必改变代码或重新编译 。
在设计应用组件时,要记住,尽管enterprise beans 有一个可使应用组件的容器自动启动多步
事务的机制,但是applet 和应用的客户容器可能并不支持这一点。然而,applet 和应用客户
容器总是能够调用支持这一点的一个enterprise bean 。
还应当注意,JSP 页面和servlets 没有被设计成是事务的,它们通常应当将事务工作交给一
个enterprise bean 来完成。然而,如果事务工作在一个JSP 页面或servlet 中是必须的,那么
此种工作也应当是非常有限的 。
可再用应用组件(可再用应用组件(可再用应用组件(可再用应用组件(Reusable Application Components )))
J2EE 组件(applets 、应用的客户、enterprise beans 、JSP 页面及servlets )
都被打包成模块,并以Java ARchive (JAR )文件的形式交付。一个模块
由相关的组件、相关的文件及描述如何配置组件的配置描述文件组成 。
例如,在组装过程中,一个HTML 页面和servlet 被打包进一个模块之中,该模块包含该HTML
文件、servlet 组件及相关的配置描述文件,并以一个Web ARchive (WAR )文件的形式交付,
该WAR 文件是一个带.war 扩展名的标准JAR 文件。使用模块使得利用相同的组件中的某些
组件来组装不同的J2EE 应用程序成为可能 。
例如,一个J2EE 应用程序的Web 版可能有一个enterprise bean 组件,还有一个JSP 页面组
件。该enterprise bean 组件可以与一个应用客户组件结合,以生成该应用程序的非Web 版本。
这不需要进行额外的编码,只是一个装配和部署的问题。
并且,可再用组件使得将应用开发和部署过程划分成由不同的角色来完成成为可能,这样不
同的人或者公司就能完成封装和部署过程的不同部分。J2EE 平台定义了如下角色:
J2EE 产品提供商(产品提供商(产品提供商(产品提供商(J2EE ProdUCt Provider )))
设计并使J2EE 平台、API 和在J2EE 规范中定义的其他特征能被其它公司或人购得的公司。
应用组件提供商(应用组件提供商(应用组件提供商(应用组件提供商(Application Component Provider )))
创建用于J2EE 应用程序的Web 组件、enterprise bean 组件、applets 或应用客户程序的公司
或个人。在装配过程中,应用组件文件、接口及类被打包进一个JAR 文件中 。
应用程序装配商(应用程序装配商(应用程序装配商(应用程序装配商(Application Assembler )))
从组件提供商获得应用组件JAR 文件,并将它们组装成一个J2EE 应用的Enterprise ARchive
(EAR )文件的公司或个人,此种文件是一个带.ear 扩展名的标准文件 。
应用装配商提供与该应用程序相关的整体信息,并使用验证工具来检验EAR 文件的内容是
正确的。组装和部署信息存储在一个基于文本的配置描述文件中,此种文件使用XML 标记
来标记该文本。应用装配商可以按照“设计企业应用”的描述直接编辑该配置描述文
件,或者使用一个能通过交互式选择来正确添加XML 标记的装配和配置工具来编辑该配置5
描述文件 。
部署商(部署商(部署商(部署商(Deployer )))
部署J2EE 应用程序的公司或个人。职责包括设定事务控制、安全属性,并根据应用组件提
供商提供的指示来标明一个enterprise bean 是自己处理自身的存储,还是由一个容器来处理
等。
部署涉及配置和安装。在配置过程中,部署商遵循应用组件提供商提供的指示来解决外部依
赖问题,定义安全设定,以及分配事务属性。在安装过程中,部署商将应用组件安装到服务
器上,并生成容器特定的类和接口。
系统管理员(系统管理员(系统管理员(系统管理员(System Administrator )))
配置并管理运行J2EE 应用程序的计算环境和网络基础设施,并监督运行时环境的人员 。
工具提供商(工具提供商(工具提供商(工具提供商(Tool Provider )))
生产被组件提供商、装配商及部署商使用的用于进行开发、组装和打包的工具的公司或个人。
设计用户界面和引擎(设计用户界面和引擎(设计用户界面和引擎(设计用户界面和引擎(Designing the User Interface and Engine )))
在为J2EE 应用程序设计用户界面和后端引擎时,我们需要决定是让
该程序基于Web ,还是不基于Web 。在做出这个决定时,我们可能希
望考虑平台配置、下载速度、安全、网络流量和网络服务 。
例如,包含有用户界面并且经常被大量用户访问的一个applet 可能需
要花很长的时间才能被下载下来,这让用户沮丧。然而,如果知道该applet 要运行在一个公
司的内部网内的受控环境中,那么,在这种情况下,该applet 将拥有一个完全可接受的下载
速度。
另一个考虑是,繁重的处理应当在哪里执行。例如,如果客户程序在一个蜂窝电话或呼机中
执行,服务器应当完成尽量多的计算和数据处理,而客户程序只应显示结果就可以了。然而,
设计在一个强大的台式机平台上运行的大型财务分析系统则应当在客户机上完成其复杂计
算。
应用的客户程序和applet 用户界面通常都是用Swing API 创建的,该API 可从标准版Java2
平台(Java 2 Platform ,Standard Edition )中获得。Swing API 提供了一整套GUI 组件(表格、
树形结构、按钮等),这些组件可以被用来实现一种比用一个典型的HTML 页面所能实现的
更为交互的体验。Swing 也支持HTML 文本组件,这个组件可以被用来显示来自一个服务
器的响应 。
客户程序可以直接访问enterprise bean 层或企业信息系统层。但应谨慎实现这种程序。绕过
EJB 层的程序可以使用JDBC API 来访问一个关系型数据库,但应被限制于对数据库表格进
行维护等这样的管理任务上 。
设计基于设计基于设计基于设计基于Web 的应用程序(的应用程序(的应用程序(的应用程序(Designing Web-Based Applications )))
基于Web 的应用程序是基于浏览器的,并且,如果它们运行在Internet
上的话,可能被全世界的人访问。当设计一个基于Web 的应用程序时,6
不仅需要决定用什么来处理内容和应用逻辑(HTML 、XML 、JSP 页面及servlets ),而且还
应当考虑使该应用程序国际化 。
一个国际化的基于Web 的应用程序向用户提供了选择一种语言,然后,根据该选定语言加
载应用的正文的方式。对被支持的每种语言而言,应用正文都被存储在一个外部文件中,并
且,与另外一个文件的关键词相对应。应用代码使用这些关键词以及选定的语言来加载正确
的文本。国际化API 还提供类来根据选定的语言来格式化日期和金钱 。
一旦制订了使应用程序国际化的细节,我们就可以决定用什么来实现它了。总体来说,一个
基于Web 的应用程序使用HTML 来显示数据; 用XML 来定义数据以使其可被另一个程序读
取并处理; 使用JSP 页面或servlets 来管理用户与业务层或存储层之间的数据流。
可以在J2EE 平台上实现的基于Web 的应用程序有四种。从简单到复杂排列,它们是 :
˙基本HTML
˙带基本JSP 页面或servlets 的HTML
˙带JavaBean 类的JSP 页 面
˙将应用逻辑根据功能划分成区域的高度结构化的应 用
当设计一个基于Web 的应用程序时,需要决定用什么来建立它。并且,如果我们是从建立
一个简单的应用程序开始着手的话,如果认为以后会给该应用程序添加功能,那么,设计应
当适应今后发展的需要。下面的内容通过比较JSP 页面和servlets ,来帮助我们做出某些设
计决定。
Servlets 和和和和JSP 页面页面页面页 面
Servlets 是实现动态内容的一种简便的、平台独立的、Web 服务器独立的方式。JSP 页面是
开发servlets 的一种基于文本的、以显示为中心的方式。JSP 页面提供了servlets 的所有好处,
并且,当与一个JavaBeans 类结合在一起时,提供了一种使内容和显示逻辑分开的简单方式。
分开内容和显示逻辑的好处是,更新页面外观的人员不必懂得Java 代码,而更新JavaBeans
类的人员也不必是设计网页的行家里手。JSP 页面和servlets 都比公共网关接口(CGI )更可
取,因为CGI 不是平台独立的,使用了更多系统开销,而且没有一个简单的方法来访问参
数数据,并将这些数据发送给一个程序 。
可以用带JavaBeans 类的JSP 页面来定义Web 模板,以建立一个由具有相似的外观的页面组
成的网站。JavaBeans 类完成数据提供,这样在模板中就没有Java 代码,这意味着这些模板
可以由一个HTML 编写人员来维护。
在选择使用一个servlet ,还是一个JSP 页面时,要记住的是,servlets 是一个程序设计工具,
它最适用于不需要频繁修改的低级应用功能; 而JSP 页面则通过以显示为中心的描述性的方
法将动态内容和逻辑结合在一起 。
对于一个使用一个JSP 页面的简单的基于Web 的应用程序,我们可以使用定制标记或者
scriptlets ,而不是使用JavaBeans 类来将内容与应用逻辑结合起来。定制标记被打包到一个
标记库中,并被引入到一个JSP 页面中。Scriptlets 是直接嵌入在JSP 页面中的很小的Java7
代码段。
模型、视图和控制器架构(模型、视图和控制器架构(模型、视图和控制器架构(模型、视图和控制器架构(Model, View, Controller Architecture )))
在基于组件的J2EE 平台充分内置了灵活性的情况下,剩下的问题可
能是如何组织应用程序以实现简单高效的应用程序升级和维护,以及
如何让不懂程序代码的人员避开程序数据。答案就在模型、视图和控
制架构(MVC )的使用之中。MVC 这样的架构是一个描述重现的问
题及其解决方案的设计范式,但问题每次重现时,解决方案都不是完
全相同。
MVC 设计范式包括三种对象:
模型(model )提供应用业务逻辑(enterprise bean 类); 视图(view )则是其在屏幕上的显示
(HTML 页面、JSP 页面、Swing GUI ); 控制器则是servlet 、JavaBean 或session bean 类,
它用于管理用户与视图发生的交互。我们可以将控制器想象成处在视图和数据之间,对视图
如何与模型交互进行管理 。
通过使视图完全独立于控制器和模型,就可以轻松替换前端客户程序。并且,通过将控制器
和模型代码保持在视图之外,那些不理解这些代码的人员就不能改变他们不应改变的东西。
将控制器和模型分开可以在不影响模型的情况下改变控制器,也可以在不影响控制器的情况
下改变模型 。
例如,如果应用的前端是一个HTML 页面,一个HTML 专家就可以更新它。如果使用一个
JSP 页面,将控制器的代码放到一个JavaBean 或session bean 类中,或使用动作标记(action
tags ),这样,JSP 页面就仅包含JSP 代码了 。
J2EE 应用程序中的应用程序中的应用程序中的应用程序中的Enterprise Beans
当编写管理特定业务功能(比如追踪雇员资料或进行复杂财务计算)
的J2EE 应用程序时,请将完成这些任务的业务逻辑放置在EJB 层的
enterprise beans 中。以这种方式,我们就可以使代码集中在解决手边
的业务问题,而利用enterprise bean 容器来支持低层服务,比如状态
管理、事务管理、线程管理、远程数据访问和安全等。
将业务逻辑与低层系统逻辑分开意味着容器可以在运行时创建和管理enterprise bean 。 按照
规范编写的任何enterprise bean ,都可以根据其在一个特定的J2EE 应用程序中将被如何使用
来对其事务管理或安全属性进行配置,并可以被部署到任何一个与规范兼容的容器中。可再
用组件使不必改变和重新编译enterprise bean 代码成为可能 。
一个enterprise bean 由接口和类组成。客户程序通过enterprise bean 的home 和远程接口来访
问enterprise bean 的方法。Home 接口提供了创建、删除和定位enterprise bean 的方法,而
远程接口则提供了业务方法。在部署时,容器由这些接口来创建类,使客户能够创建、删除、
定位或调用位于enterprise bean 上的业务方法。enterprise bean 类提供了业务方法、创建方法
和查寻方法的实现。如果enterprise bean 管理它自己的持久性的话,还为其生命期方法提供
了实现。8
有两种Enterprise beans :entity beans 和session beans 。
一个session bean 代表与客户程序的一个短暂的会话,而且可能执行数据库读写操作。一个
session bean 可能会自己调用JDBC ,或者它可能使用entity bean 来完成此种调用。在后者这
种情况下,这个session bean 是该entity bean 的客户。一个session bean 的域包含会话状态,
而且是短暂的。如果服务器或者客户程序崩溃,该session bean 就丢失了。这种模式通常被
用于像PL/SQL 这样的数据库程序设计语言上 。
一个entity bean 代表一个数据库中的数据及作用于该数据的方法。在一个关系型数据库中的
雇员信息表中,每一行都有一个bean 来代表。entity beans 是事务的,并且是长寿命的。只
要数据留在数据库中,entity bean 就存在。这个模式可以被很容易地用于关系型数据库,而
不仅限于对象数据库。
Session beans 可以是有状态的,也可以是无状态的。一个有状态的
session bean 包含代表客户程序的会话状态。该会话状态是该session
bean 实例的域值加上这些域值所引用到的所有对象。有状态session
beans 并不代表在一个持久数据存储中的数据,但是,它可以代表客
户程序访问和更新数据。
无状态session beans 没有用于某个特定客户程序的任何状态信息。它们通常被用于提供不保
持任何特定状态的服务器端行为。无状态session beans 要求更少的系统资源。一个提供一种
一般服务,或用于表示被存储的数据的一个被共享的视图的业务对象是无状态session bean
的一个例子 。
因为enterprise beans 占用可观的系统资源和带宽,可能希望将某些业务对象构造成数据访问
对象或值对象。数据访问对象完成诸如代表客户程序访问数据库等工作。值对象用于代表容
纳数据字段并提供简单的“get 和set ”方法来访问这些数据的一个结构 。
另外,可以将程序构造成使用enterprise bean 在客户和EJB 层的其它部分之间承担通信的任
务 。
一个使用容器管理的持久性来访问一个关系型数据库的enterprise
bean ,并不要求在bean 的代码中使用任何JDBC 2.0 API 来进行数据库
访问,因为容器完成了这些工作。然而,如果使用bean 管理的持久性,
或者我们要访问一个非关系型数据库的企业信息系统,那么我们就必
须在bean 中提供相应的代码来完成这些工作 。
在一个enterprise bean 使用bean 管理的持久性来访问一个数据库的情况下,必须使用JDBC
2.0 API 代码来实现该enterprise bean 的生命期方法,以便处理数据的加载和存储,以及在运
行时系统和持久数据存储之间维持数据的一致性。
一个使用bean 管理的持久性的enterprise bean ,或一个需要访问企业信息系统的Web 组件必
须提供合适的代码。这些代码可能是用于进行数据库访问的JDBC 2.0 API ;或是用于访问一
个特定企业信息系统的企业信息系统API ;或是用于抽象企业信息系统API 的复杂性和低层
细节的一个访问对象,或是用于访问企业信息系统资源的一个连接对象。9
尽管Web 层使用HTTP 或HTTPS 来在各层之间传输数据,但是,EJB 层使用的是RMI-IIOP 。
RMI-IIOP 是一个完整的分布式计算协议,能让任何访问一个enterprise bean 的客户层程序或
Web 层程序直接访问EJB 层的服务。这些服务包括用于查找和引用enterprise beans 的JNDI ,
发送和接收异步消息的Java Message Service (JMS ),以及用于关系型数据库访问的JDBC 。进入讨论组讨论。
(出处:http://www.knowsky.com)