UML软件工程组织

J2EE打包与部署
作者: 务实
Thursday, September 18 2003 3:42 PM  

J2EE平台的主要特色之一在于开发人员可以在其之上整合不同的组件,这个将组件整合为模块并将模块整合为商业应用程序的过程叫做打包。而在一个可使用环境的安装和定制应用程序的过程则叫做部署。为了能够更好地被定制,应用程序的组件需要是可配置的,然而,开发人员不应该持续开发不同的配置机制,相反地,使用标准机制并对配置过程提供相当的灵活度是非常重要的。J2EE平台为打包和部署提供了相应的工具,使得其过程相对简单。主要来说,它使用Java档案文件(JAR)作为组件和应用打包之后的标准整合结果,同时它还使用基于XML的描述文件来配置组件和应用程序。J2EE技术规范为J2EE应用程序的结构建立和生成提供了指导,其中一条原则就是与打包(packaging)有关,具体的技术规范为诸如EJB、JSP网页和servlet等组件的打包提供了指导;J2EE平台规格描述提供一个将一个或多个组件集成为一个模块的方法,即为任何组件类型的最小单元提供独立部署,一个模块可以直接部署至J2EE容器中,或多个模块可以集合起来组建一个J2EE应用程序;例如,几个ejb组件可以被打包为应用模型中的一个EJB模块,同时这个EJB模块也可以进一步与其他模块结合以建造一个完整的J2EE应用。

一、J2EE打包综述

一个J2EE应用程序包括下列部分:一个或者多个J2EE组件;一个J2EE应用程序实施描述符。    在一个或者多个异类J2EE组件需要彼此使用对方的时候,必须生成一个J2EE应用程序(application)。在建立一个J2EE应用程序时必须考虑到多个方面,其中包括:

  • 可以打包成一个J2EE应用程序的J2EE组件类型;
  • 当人们生成J2EE包时扮演的角色;
  • 当前的J2EE打包限制;

不同厂商为满足J2EE组件交互而采用的类装入方式。

1、J2EE打包组件

    一个J2EE组件,例如servlet或EJB,是与组件描述中定义的接口保持一致的独立功能软件单位,并且这类软件很明显地依赖于其生存环境。组件也许是一个单一的类,但也经常是类、接口和资源的集合。J2EE平台提供五种类型的组件:EJB,servlets和JSP,applet,应用客户程序以及连接器(connector)。

    J2EE平台中的模块和应用程序被作为部署单元而打包和部署,这种过程所得到的压缩文档与JAR文件类似,但具有一个指定的内部结构和文件扩展名。通常来说,存在四种不同类型的J2EE平台模块:

    (l)EJB模块,其中包含ejb文件及相应类;EJB模块是一个可实施的单元,包括EJB、关联的库JAR文件以及资源。 EJB模块被预打包成JAR文件,在JAR文件的META-INF目录中有一个实施描述符 (ejb-jar.xml)。

    (2)Web模块,其中包含Web层的组件及资源;Web模块是一种可以实施的单元,由Java Servlets、JSP网页、JSP标志库、库JAR文件、HTML/XML文档及其他公共资源如图片,applet类文件等组成。一个Web模块打包成一个Web ARchive file,也称为一个WAR文件。WAR文件类似于JAR文件,只是WAR文件包含一个WEB-INF目录,在web.xml文件中包含实施说明。

    (3)应用客户模块,其中包含应用客户类;应用程序客户模块JAR文件包含一个独立的Java应用程序,它将要在应用程序客户容器中运行。这个应用程序客户JAR文件包含一个专门化的实施描述符,其构成与EJB JAR文件类似。JAR文件包含运行独立的客户所需的类,当然还包括访问JDBC、JMS、JAXP、JAAS或者EJB客户所需的任何客户库。

(4)资源适配器模块,其中包含Java连接器(connector)、资源适配器和帮助库函数及相关资源。资源适配器RAR文件包含在一个企业信息系统中实现一个Java Connector Architecture(JCA)资源适配器所需的本机(native)库和Java类。资源适配器并不在一个容器内执行,而是设计成一个桥梁在应用程序服务器和外部企业信息系统之间运行;这些部件每个都是单独开发和打包的,除了J2EE EAR文件和自己的实施描述符之外;J2EE EAR文件是一个或者多个这些组件的一种结合,成为一个带有自定义实施描述符的统一的包。

2、打包角色

在建立、实施和使用EJB、Web应用程序或者其他组件时,不同的人将扮演不同的角色。J2EE技术规范定义了一个宽泛的系统平台角色(platform role),这是开发者在生成企业应用程序时扮演的。尽管在开发和实施过程中人们会想到有多种角色,但实际上这些角色只不过是一些逻辑上的概念,目的是使得人们可以更好地规划和执行一个应用程序。一个人或者机构很可能(而且希望是)具有多重角色。EAR文件的建立、实施或者使用中的普通角色包括:

  • J2EE产品提供者 

J2EE产品提供者提供了J2EE系统平台的一个实现,其中包括所有适当的J2EE API及此技术规范中定义的其他特性。J2EE产品提供者典型情况下是一个应用程序服务器,Web服务器或者数据库系统厂商,它通过把技术规范和组件映射到网络协议而提供了一个适当的实现。

  • 应用程序组件提供者

 应用程序组件提供者提供了一个J2EE组件,例如一个EJB应用程序或者一个Web应用程序。在J2EE技术规范中还有许多角色可以具有应用程序组件提供者的特点。这些包括文档开发者、JSP作者、企业bean开发者和资源适配器开发者。

  • 应用程序组装者 

应用程序组装者负责把一个或者多个J2EE组件结合到一个EAR文件中以生成一个J2EE应用程序。应用程序组装者还负责生成J2EE应用程序实施描述符,并且标识出此应用程序可能需要的任何外部资源。其中包括类库、安全性角色和命名环境。应用程序组装者一般将使用J2EE产品提供者和工具提供者提供的工具。

  • 工具提供者 

工具提供者提供相关的实用程序来自动实现J2EE应用程序的生成、打包和实施。工具提供者可以提供相关的工具来自动为一个EAR文件生成实施描述符、生成EAR文件以及把EAR文件实施到应用程序服务器。工具提供者提供的实用程序既可以是独立于系统平台的(适用于不论任何环境下的所有EAR文件),也可以是与系统平台相关的(适用于一种特定环境下的本机功能)。

  • 实施者 

实施者负责把Web应用程序和EJB应用程序实施到服务器环境中。实施者并不负责实施资源适配器档案文件或者应用程序--客户档案文件,但也可能会负责这些组件的相关配置。这些组件即使是作为J2EE EAR文件的一部分打包,在企业应用程序实施的时候也不会被考虑。它们是J2EE应用程序的组成部分,但并不通过一个运行时的“激活过程(activation)”而组合,而Web应用程序和EJB容器在实施过程中要经过这个激活过程。资源适配器档案文件就是一个合法JCA实现的库。尽管它们被打包成一个J2EE EAR文件的组成部分,但它们并不在J2EE容器的上下文环境中运行。因此,由于资源适配器档案文件并没有J2EE容器,它们在激活过程中也不需要有J2EE实施者。

应用程序客户程序确实是在J2EE容器的上下文环境中运行,但是它们并不实施在应用程序服务器中。应用程序客户程序独立运行,实施者并不负责为这些程序配置容器环境。

实施者生成准备好供容器使用的Web应用程序、EJB应用程序,applet和已经针对应用程序服务器的目标环境定制的应用程序客户。

  • 系统管理员 

系统管理员负责配置网络和运行环境供应用程序服务器和J2EE应用程序在其中运行。系统管理员还负责监视和维护J2EE应用程序。

3、打包的限制

EAR文件满足了打包应用程序的基本要求, 因为大多数基于Web的J2EE应用程序完全由Web和EJB应用程序组成。但是EAR文件缺乏打包复杂的J2EE应用程序的能力。例如,下列组件不能在一个EAR文件中被声明,但经常用于一个J2EE应用程序:

  • JDBC DataSource对象;
  • JMS ConnectionFactory和Destination对象;
  • JMX Mbeans;
  • 在应用程序服务器中运行的一些JMS消费者,如MessageConsumer作为SeverSession的一部分运行;
  • 当应用程序被实施和卸出(un-deployed)时触发的类。(这些类是由厂商提供的专门扩展,不是J2EE技术规范的规定。但是,所有的厂商一般都提供它们。)

目前这些组件都需要被手工配置以及通过实施厂商提供的管理接口配置和实施,并且这也是系统管理员的责任。随着时间的推移,这些项目的使用将会增加,因而EAR文件支持这些组件的打包也是很重要的,以便使应用程序的移植成为可能。

二、 打包J2EE应用程序

一个J2EE应用程序可以被打包为一个可移植的部署单元,称为商业档案文件(enterprise archive)。一个商业档案文件是一个标准的Java档案文件并带有ear扩展名。这样的文件包括一个或多个J2EE模块及一个J2EE应用程序的部署描述文件。

J2EE应用程序的制作过程主要分为两步:首先,应用组件提供商负责开发EJB模块、Web层程序和应用客户模块。其次,应用程序集成商将这些模块打包在一起以创建一个可以部署的J2EE应用模块。同时应该说明的是,所有J2EE模块都是独立的可部署单位。这使组件提供者无需实现全部应用即可开发独立的功能单元。但是,我们需要对具体的打包概念和操作有一定理解。下图1说明各种类型的J2EE 模块(EJB、Web、应用客户和应用程序)及它们怎样被部署。虽然这个图只显示了一个独立的被部署的EJB模块,但是所有这四种类型的J2EE模块都可以被独立地部署。为了整合一个应用程序,应用程序整合人员将通过设定相应模块的部署描述文件之间的连接来解决组件之间的依赖关系。每个组件都可能在同一个档案文件中与其他组件具有依赖关系,或是在不同档案文件中。这些依赖关系都必须在部署之前解决。整合人员要保证相同组件在不同的档案文件中的描述保持一致。

图1 J2EE程序包结构

J2EE规格对于组件和部署单元设置一定数量的需求,多数来说都是为适当的组件操作而准备的,但是组件容器并不需要实时执行这些规则中的大多数。

1、EJB模块

一个EJB模块通常被包装和部署为EJB Java档案文件和一个带有jar扩展名的Java 档案文件。这是ejb最小的可部署和可使用单位。一个标准的EJB模块包括:

  • Java类文件,包含enterprise bean定义及其本地和远程接口;
  • EJB代码中所依赖的Java类文件。这里是指在J2EE平台之外的代码文件;
  • EJB部署描述文件,其提供了应用程序中用于enterprise bean的结构和整合信息。通常来说整合信息是可选的,并且只包含在整合应用程序中。

应该说明的是,ear文件与标准的jar文件存在显著的区别:ear文件包含一个部署描述文件,它包含了一个或多个enterprise bean的主要形容信息。

EJB Java档案文件除了可以在服务器端使用之外,一个EJB Java档案文件开发人员还可以开发包含用户程序需要访问的EJB类文件,这些类大多数包含在EJB Java档案文件。应该注意的是,服务器端的组件实现类文件通常不会包含在客户端的Java档案文件。在EJB Java档案文件中或client Java档案文件中的类可以直接在类文件中引入,或在外部引用中声明。

2、EJB模块打包准则

  • 如何将组件打包成EJB模块

一个典型的商业应用通常包括多个ejb,其中一些ejb可能是商用组件,或是其他的第三方库函数;而应用集成人员可能从以下方法中选择:

1)将应用程序中的每个ejb包装在自己的EJB模块中。在这种方法里,每个ejb具有自己的部署描述文件并与其依赖的类文件一起打包在ejb模块中。这个方法的好处在于它可以最大化每个ejb的可重用性,并留给应用集成人员很大的自由在ejb模块中选择以建立J2EE应用程序。如果开发人员的ejb具有很强的可重用性,这种方法是值得推荐的。在这种情况下,应用集成人员可以准确地重复利用他们希望重复利用的那些ejb。

2)在同一个EJB模块里包装应用程序中所有ejb。在这种方法中,所有ejb和它们的依赖类被一起包装在一个EJB模块里。这种方法较其他方法实施起来是最简单的。

3)将所有与一个应用程序有关系的ejb打包在一个EJB模块里。在这种方法中,所有的ejb将根据它们功能上的特性分类并放置在同一个ejb模块中。

  在以上几种方法中,第三种选择模块性最好,并被许多J2EE应用程序采用。这主要是因为这种方法可以取得可重用性和简单性的平衡。同时它也促进了第三方组件的黑箱操作,这对于包含很多数字签名的组件的应用系统是十分重要的。另外这种方法在J2EE服务器需要部署在不同Java虚拟机上的各个ejb模块时尤其有效,它可以将相关联的ejb编组在一起,同时允许远程调用。

  • JNDI命名空间内的本地接口

    大多数EJB实现程序都是通过Java命名和目录接口(Java naming and directory  interface)来定义ejb本地接口的,一个部署描述文件通常会将组建的ejb命名编入进其JNDI命名中。不过由于通常没有对本地接口的远程访问,本地接口是无需在全局的JNDI命名空间内公布的。在组件通过JNDI寻找本地接口时,ejb容器并不需要通过JNDI命名空间到处提供本地bean的实现,相反地,ejb容器需要实现所有本地接口的JNDI查找,并根据请求返回相应的对象。

  • EJB模块部署建议

ejb类文件通常会有没在bean本地和组件接口声明的公共方法。部署描述文件不应该为这些方法制定事务或安全属性。由于ejb容器只会作用于公共组件或本地接口的方法调用,所以它可以为这些方法提供事务支持或安全限制。

在某些时候,容器管理的实体bean的主键类可能对于组件提供商来说是未定义或未知的,这时,开发人员可以将实体bean的部署描述文件中的主键设置为java.lang.Object。

一些实体bean可能作用于数据库中的商业数据,包括在容器管理的持久性下管理和更新这些数据。开发人员需要认识到如果取消这些bean的部署,那么它们所管理的数据表格也将会被删掉。同时,相同的组件也可能在一个应用程序的多个地方被应用,而当这些bean使用容器管理的持久性时,开发人员需要考虑是否将该组件的所有实例存储在一个表中或多个表中,并适当地配置其持久性行为。

3、Web模块

Web模块通常是被打包并部署为Web档案文件(Web archive,WAR),即Java档案文件带有.war扩展名。这种文件也是Web资源中最小的可部署和可用单元。通常一个Web模块包含:

  • Servlet的Java类文件及其依赖文件;
  • JSP文件及其帮助类;
  • 静态文档,html页,图像,声音文件;
  • Java Applet及类文件;
  • Web部署描述文件。

与其他部署单元类型不同,WAR文件通常不能由一个类载器(classloader)上载,这主要由于其内部结构和一个可载入的JAR文件是不同的;与其他模块类型一样,一个WAR文件可以作为一个Web应用独立地部署或包含在EAR文件中,一起部署为一个J2EE应用程序。

4、应用客户模块

应用客户模块通常是打包在Java档案文件并带有.jar扩展名,应用客户模块通常包括实现客户端程序的Java类文件和应用客户部署描述文件; 一个应用客户通常会使用EJB JAR文件提供商提供的客户jar文件,而这个客户jar文件由用户需要访问的ejb类文件组成。

5、资源适配器模块

 一个Java连接器(connector)通常被打包和部署为一个资源适配器(resource adapter archive)文件,即一个jar文件并带有.rar扩展名。这也是java连接器最小的可部署和可用单元。一个资源适配器模块(resource adapter module)包括;

  • 实现连接器体系结构及适配器的类文件和接口文件;
  • 资源适配器的使用类;
  • 资源适配器的支援库函数;
  • 帮助文件;   
  • 资源适配器的部署描述文件。
三、J2EE部署

J2EE的部署就是应用构件按照一定的格式打包并放置在应用服务器的容器内,在部署时,J2EE提供的部署服务允许对应用构件进行设置;在J2EE构件被安装在容器内时,它们一般是根据功能被分成若干个模块,每个模块都有一个部署描述文件(deploy descriptor)用于告诉J2EE容器如何进行部署;这个描述文件是一个基于XML的文本文件,部署描述文件包含许多与应用构件和J2EE平台服务有关的元素,譬如构件如何使用事务和安全服务等等。

    一个J2EE程序包括一个或多个J2EE模块和一个J2EE应用部署描述文件(不同于模块的部署描述文件),该应用部署描述文件告诉J2EE应用服务器所需要部署的程序模块和如何对这些模块进行设置;一个J2EE程序就是一个企业档案文件(EAR),EAR文件采用压缩文件格式(像常用的zip文件),一个EAR文件包括一个或多个Java档案文件(JAR)以及零个或多个资源档案文件(RAR)。

    J2EE有四种模块,每种模块对应一类构件。EJB模块包含EJB的类文件EJB的部署描述文件。EJB模块被打包成以.jar为扩展名的JAR文件;Web模块包含JSP文件、为servlets程序编译后的类文件、GIF和HTML文件以及Web部署描述文件,Web 模块被打包成以.war为扩展名的WAR文件;其实WAR文件格式和JAR基本相同,可以认为WAR文件是特殊的JAR文件;资源适配器模块(resource adapter)包含所有Java接口、类和其他文件,以及资源适配器的部署描述文件。这些类用来实施由企业信息相同EIS的连接。资源适配器模块被打包成以.rar为扩展名的JAR文件;应用客户模块包含客户程序的类文件和一个应用客户部署描述文件,应用客户模块用JAR文件格式。

在上述每种类型的模块中,每个部署单元都具有相应组件描述定义的组件结构。例如,Web模块部署单位被称为Web档案(Web archive),它具有一个WEB-INF目录以包含所有支持文件。一个或更多J2EE平台模块可以组成一个J2EE应用程序,它包含它自己类型的部署单位;除组件和资源之外,各个部署单位包含一个部署描述文件,它是一个指定各组件与其环境之间的关系的XML文件。部署描述文件包含以下两种信息:

    (1)结构信息:它主要描述包含在部署单位中的组件信息,包括它们之间的关系和依赖性。通常这类信息包括ejb home和远程接口及实现类、实体bean主键类、持续性机制及环境声明变量和资源需求;一个组建容器将会使用结构信息来实时地管理组件实例。

    (2)集成信息:这是一种可选择的信息,描述了一个部署单位如何与其他部署单位集成并制造出新的组件,这类信息通常包括ejb关系名、描述符、安全角色信息、方法许可和环境变量值。

1、部署描述文件

部署描述文件(deployment descriptors)描述部署单位内容并相对于应用环境配置组件和应用程序。同时对它们与组件之间的关系做出了一定的处理,从而可以在无需编程的情况下对这些关系加以管理。部署工具通常会自动生成部署描述文件,所以开发人员不必直接编辑和管理它们。

通常部署描述文件有四种类型,每种对应于一个类型部署单位:

  • EJB部署描述文件;
  • Web层部署描述文件;
  • 应用客户部署描述文件;
  • 资源适配器部署描述文件。

各种部署描述文件的定义都可以在相应的XML文档类型定义(document type definition)中找到。部署描述文件包含由组件容器使用的信息及组件通过JNDI访问的信息。

   有关EJB部署、应用客户部署及资源适配器部署请读者参考有关J2EE资料,在此就不多说了,下面我们讨论一下Web层部署内容。

2、Web程序部署

   Web程序的部署主要包括将Web程序以标准格式打包和将Web程序放入Web服务器中运行两步。Web程序的部署描述文件(deployment descriptor)建立了Web程序和Web程序服务器之间的信息交流。一个部署描述文件采用符合特定标准的格式来描述一个Web程序内的构件(如servlet,filter,listener,JSP等)和使用方式(如安全机制、错误处理方法等)。当Web程序服务器启动并加载一个Web程序时,它会根据其部署描述文件设置其运行状态并初始化Web构件。

1)web.xml文件的格式

   由于Web程序开发中各种人员有不同分工,而Web程序的部署描述文件是程序构件提供者、程序组装者和程序部署者之间的沟通机制;Servlet 2.4之前的版本规定了在Web服务器中使用DTD格式的web.xml,而Servlet 2.4将依照XML schema格式定义web.xml;实际上这两种格式的web.xml只是在头部有区别,其内容都是描述Web程序的部署信息。在web.xml中出现的部署元素主要包含以下信息:

  • ServletContext的初始化变量(Init Parameters);
  • 交互会话(Session)的设置;
  • Servlet的声明定义;
  • Servlet和网址URL的映射(Mapping);
  • 应用程序生命周期的监听器(Application Lifecycle Listener);
  • 过滤器声明;
  • 过滤器和网址URL或Servlet/JSP的映射;
  • MIME类型;
  • 欢迎文件(Welcome File);
  • 错误网页(Error Pages);
  • 安全设置信息;
  • taglib配置;
  • JNDI对象(env-entry,ejb-ref,ejb-local-ref,resource-ref,resource-env-ref)。         

其中taglib配置与JNDI对象这两项是支持J2EE的Web服务器必须要求的。对于不支持J2EE的servlet/JSP服务器,不需要这两项;在web.xml中的元素需要按照规定的大小写和顺序出现。

2)Web程序结构和部署方式

在设置了部署描述文件后,需要对Web程序进行编译和打包,一个Web程序需要依照标准的目录和文件格式组织其内容。例如在Tomcat 5.0中的目录和文件格式,其中WEB-INF目录中有web.xml部署描述文件和包括该Web程序Java类的classes目录。在Web服务器中部署Web程序的方式有两种:一种是直接将依照标准格式的Web程序的整个目录编译后放入Web服务器的webapps目录,这样Web服务器启动时会自动加载Web程序;另一种是将Web程序编译并打包生成一个war文件,然后放入Web服务器的webapps目录。Web服务器可以选择不需解压直接加载这个Web程序的war文件,或者将这个war文件解压到一个目录后加载。在/conf/server.xml中可以设定选择何种加载方式。如果<Host>标记的unpackWARs="flase",表明Web服务器不需要将war文件解压成目录;如果unpackWARs="true",表明Web服务器会在第一次加载Web程序时将该war文件解压成一个目录。

<Host name="localhost" appBase="webapps" debug="0" unpackWARs="false">

第二种方式的优点是增强了Web程序的可移植性,一个war文件可以在不同的符合标准的Web服务器中运行而且文件比较小;当需要将Web程序给予其他人员时,给对方一个war文件当然比给一个目录方便;但是生成war文件需要将一个Web程序的目录进行压缩,在调试过程中,如果编程者需要经常对程序的某些部分进行改动,使用第一种方式就比较方便。每次需要改动时就在webapps的Web程序目录中用改动的文件替代旧的文件,而不用每次打包生成war文件。

3)使用编程工具编译和打包

一个war文件就是有特定格式(如WEB-INF目录)的jar文件,它将一个Web程序的所有内容进行压缩。在生成war文件之前,所有WEB-INF/classes目录下面的servlet,filter等类需要首先被成功编译,最基本的方法是直接使用javac命令编译所有的类。需要注意的是classpath环境变量要包括最新的servlet和JSP的jar,为了简单高效地编译Web程序并进行打包,可以使用提供Web程序管理功能的开发工具(IDE),比如Sun的Forte for Java IDE提供非常方便的Web程序开发环境,它可以统一管理程序的classpath和Java文档,用来编写大型的J2EE程序非常方便。可以使用Web服务器的deploytool打包,比如sun的JWSDP1.0就提供了一个图形界面的deploytool;也可以使用Apache软件组织开发的Ant(蚂蚁)工具进行编译和打包,完成Web程序部署。

参考资料:

《Java 2 参考大全》       Herbert Schildt        清华大学出版社

《Java 2 应用开发指南》    飞思科技产品研发中心  电子工业出版社

《21天学通J2EE》           Martin Bond           人民邮电出版社


作者:务实,多年从事J2EE网站及应用系统项目的开发和应用。
 

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