您的位置 首页 java

Java高级编程基础:简单说说JAR文件结构和复杂服务扩展配置

JAR 文件

我们知道 Java 语言的出现主要是解决跨平台开发问题,为此Java语言设计了JVM规范,为了能够不受底层平台的影响,它规定了产品的发布格式。

为了管理我们开发过程中众多文件和资源,我们为开发的每一个应用程序都会是一个系统工程,不同的内容体现为不同的目录和文件。

比如类文件,资源文件,第三方类库等等,它们都有自己的文件格式和目录结构定义。

通过Java的编译和打包工具,我们可以将开发完成全部系统工程内容进行压缩打包成一个可以发布的独立文件包。

那就是Java归档文件(Java ARchive file)俗称 jar包 。它是一种基于流行ZIP文件格式的文件格式,用于将多个文件聚合为一个文件。同时将各自文件信息统一集中到一个清单文件中保存管理。

当然在此基础上我们可以进一步细分为专门用于Web应用程序的发布格式WAR,专门用于安卓发布文件格式APK,企业级归档文件EAR等等。

其实都是一种清单管理文件。该文件包中,有约定好的目录结构,有入口文件和层级分类的功能文档目录。

清单文件 Manifest File

每个JAR文件都包含一个清单文件,描述归档文件的特性。默认情况下,每个JAR文件都有一个清单文件。

默认的清单文件被命名为Manifest.MF和位于归档文件的META-INF子目录中。

虽然一般情况下默认的清单文件只包含两个条目,但是复杂的清单文件可以包含更多的条目。

清单文件的条目被分成几个部分。每个节都有两个条目节名及其值。

清单文件中除了包含相关的版本信息外号,好包含作者签名,验证等信息。

特别是它作为发行件的入口需要指定主类名称。

注意,在指定主类时,不应在类名末尾添加.class扩展名。

我们只需设置 Main-Class: Classname即可。

另外,清单的文本文件必须使用UTF-8 编码 ,在文件末尾添加新行。

服务提供者配置目录

对我们开发人员来说,这里面大部分的内容都是打包工具自动管理的,我们只需要在开发的时候,配置好我们需要打包的内容,以及打包生成的目录即可。但这里面有一个内容我们可能会在开发中经常用到,那就是有一个专门的服务提供者配置目录:

META-INF/services 
 

我们知道,在用Java语言开发应用程序是,我们一般将服务首先抽象为接口或者 抽象类 定义出来,然后在通过各种具体的类来具体的实现它们,从而提供真正的服务,这些类被称为 服务的提供者

通常这些服务提供者都是以JVM的扩展形式部署安装到服务器上,也就是说它们打包成的jar包文件是可以放置到应用程序服务的任何一个扩展目录中的。比如jre的ext文件,我们的jar包的classpath目录等等。

由于我们的服务通常由接口和抽象类表示。而特定服务的提供者会包含一个或多个具体类,这些类使用特定于提供者的数据和代码扩展实现此服务类。

我们一般所定义的服务提供者,实际上仅是一个代理,它包含足够的信息来决定真正提供者是否能够满足其特定的请求,它们甚至会根据需要创建实际提供者的代码。

而具体的提供者类的实现细节往往是高度特定于服务的。我们不可能通过定义一个类或接口来统一它们,所以这里就是可扩展的地方。

这里强制执行的唯一要求是服务提供者类必须有一个零参数构造函数,以便在查找期间实例化它们。

服务提供者的配置

服务提供者通过在资源目录META-INF/services中放置一个提供程序配置文件来标识自己。

文件的名称应该由我们定义的抽象服务类的完全限定名组成。

其文件内容应该包含一个由新行分隔的列表,其中包含唯一的具体提供程序类名。

空格和制表符以及空行都会被忽略。

注释字符是’#’,并且该文件必须用UTF-8编码。

比如,假设我们有一个名为java.io.spi.CharCodec的服务类,它定义了两个抽象方法:

public abstract CharEncoder getEncoder(String encodingName);
public abstract CharDecoder getDecoder(String encodingName);
 

每个方法都返回一个适当的对象,如果不能转换给定的编码,则返回null。

这是一个典型的字符编解码器服务(CharCodec)提供程序,它将支持多种编码器实现。

现在我们假定sun.io.StandardCodec是CharCodec服务的提供者,那么它的jar文件将包含 META-INF/services/java.io.spi.CharCodec 文件,其文件内容将是如下内容:

sun.io.StandardCodec
 

要为给定的编码名称定位编码器,内部I/O代码将执行如下操作:

CharEncoder getEncoder(String encodingName) {
 Iterator ps = Service.providers(CharCodec.class);
 while (ps.hasNext()) {
 CharCodec cc = (CharCodec)ps.next();
 CharEncoder ce = cc.getEncoder(encodingName);
 if (ce != null)
 return ce;
 }
 return null;
 }
 

提供者查找机制总是在调用者的安全上下文中执行。受信任的系统代码通常应该从特权安全上下文中调用该类中的方法。

类路径

关于类路径,我们的应用程序的清单可以指定一个或多个相对url,这些url引用应用程序所需的JAR文件和其他库的目录。

注意这些相对url都低相对于加载包含应用程序的代码根目录被处理的。

而这个代码根目录也就是类路径是使用清单文件中属性Class-Path的值指定的。

如果在主机Java虚拟机上找不到其他库的实现,则此属性会列出了搜索这些实现的url。

这些相对url可能包括应用程序所需的任何库或资源的JAR文件和目录。

假定没有以斜杠(/)结尾的相对url引用JAR文件。例如:

Class-Path:  servlet .jar infobus.jar acme/beans.jar images/
 

目前,出于安全原因,url必须相对于JAR文件的代码根目录。因此,远程可选包将必须来自与该应用程序相同的代码库。

每个相对URL都根据加载包含应用程序或库的代码根目录解析。如果生成的URL无效或引用了无法找到的资源,就会被忽略掉。

要生成的URL用于扩展应用程序、applet或servlet的类路径,方法是在包含JAR文件的URL后面的类路径中插入URL。

JAR文件规范

JAR文件是一种基于流行ZIP文件格式的文件格式,用于将多个文件聚合为一个文件。

JAR文件本质上是一个zip文件,其中包含一个可选的META-INF目录。

可以使用命令行JAR工具创建JAR文件,或者使用Java平台的java.util.jar API来构建。

JAR文件的名称没有限制,它可以是特定平台上的任何合法文件名。

在许多情况下,JAR文件不仅仅是java类文件和/或资源的简单归档。它们被用作应用程序和扩展的构建块。

META-INF目录(如果存在的话)用于存储包和扩展配置数据,包括安全性、版本控制、扩展和服务。

META-INF目录下的其它内容

Java 2平台可以识别和解释META-INF目录中的以下文件/目录,来配置应用程序、扩展、类加载器和服务。

MANIFEST.MF

清单文件,用于定义扩展内容和包相关数据的清单文件。

INDEX.LIST

此文件由jar工具的新“-i”选项生成,该选项包含应用程序或扩展中定义的包的位置信息。它是JarIndex实现的一部分,类加载器使用它来加速类加载过程。

x.SF

AR文件的签名文件,“x”表示基本文件名。

x.DSA

与具有相同基本文件名的签名文件关联的签名块文件,此文件存储相应签名文件的数字签名。

总结一般的主要属性

清单版本: 定义清单文件版本。该值是一个合法的版本号,如上面的规范所述。

Created-By: 定义生成此清单文件的java实现的版本和供应商。此属性由jar工具生成。

签名版本: 定义jar文件的签名版本。该值应该是一个有效的版本号字符串。

类路径: 此属性的值指定此应用程序或扩展所需的扩展名或库的相对url,该url由一个或多个空格分隔。

应用程序或扩展类装入器使用此属性的值来构造其内部搜索路径。

为独立应用程序定义的属性:此属性由绑定到可执行jar文件中的独立应用程序使用,java运行时可以通过运行“java -jar x.jar”直接调用这些可执行jar文件。

Main-Class: 这个属性的值是主应用程序类的类名,启动程序将在启动时加载这个类。但值不能在类名后面附加.class扩展名。

文章来源:智云一二三科技

文章标题:Java高级编程基础:简单说说JAR文件结构和复杂服务扩展配置

文章地址:https://www.zhihuclub.com/180182.shtml

关于作者: 智云科技

热门文章

网站地图