赛迪网 > IT技术 Java > 最新更新
  IT资讯搜索
 
IT产品搜索
[程序开发][网管世界][网络安全][数据库技术]
[操作系统][嘉宾聊天·在线访谈][活动集锦]
[精彩专题][Symantec专区][订阅IT技术周刊]
[开发论坛][网管论坛][安全论坛][数据库论坛]
[操作系统论坛][Sybase专区][IBM dW技术专区]
[病毒求助][病毒与漏洞播报][文档·源码下载]

教您怎样简化Java应用程序的打包和发布

发布时间:2005.12.09 10:08     来源:赛迪网开发者论坛    作者:Jackie

什么是Jar文件?

在开发过程中,我们可以直接使用Java class文件来运行程序,但这并不是一个好方式,好在Java 提供了 Jar(Java Archive)文件来提供发布和运行。

Jar 文件实际上是class 文件的ZIP压缩存档,这种格式被广泛使用,因此易与使用,有很多中工具可以操作这种格式的文件。也正是因为这个原因,Jar文件本身并不能表达所包含应用程序的标签信息。

Manifest 因此得以出现

为了要提供存档的标签信息,Jar 文件指定了一个特定目录来存放标签信息:META-INF 目录,其中我们来关注该目录中的MANIFEST.MF文件,他就是Jar的manifest文件,他包含了Jar文件的内容描述,并在运行时向JVM提供应用程序的信息,大多数Jar文件含有一个默认生成的manifest 文件,执行Jar命令或使用zip工具,都可以产生它

如果是由Jar命令产生的 manifest 文件,形如:

Manifest-Version: 1.0
Created-By:1.4.0-beta
(Sun Microsystems Inc.)

这些信息没甚么用,仅仅告诉我们使用的是1.0的manifest文件,第一行定义manifest的格式,第二行说明使用 SUN 的JDK1.4的Jar工具生成该文件,如果manifest文件是由其他 (如ant) 创建的,那将会出现 “Created-By: Ant 1.2” 之类的内容,如果你是自己创建manifest文件,你可以加入自己的一些相关信息。

基础格式

manifest 文件的格式 是很简单的,每一行都是 名-值 对应的:属性名开头,接着是 ":" ,然后是属性值,每行最多72个字符,如果需要增加,你可以在下一行续行,续行以空格开头,以空格开头的行都会被视为前一行的续行。

所有在开头的属性都是全局的,你也可以定义特定class或package的属性,稍后将介绍这种把manifest文件插入Jar文件,使用 m 选项,把指定文件名的manifest文件传入,例如:

Jar cvfm myapplication.Jar

myapplication.mf -C classdir

如果你使用ant来创建时,在ant 的build.xml 加入如下条目:

<target name="Jar">
<Jar Jarfile ="myapplication.Jar"
manifest="myapplication.mf">
<fileset dir="classdir"
includes="**/*.class"/>
</Jar>
</target>

运行Java程序

现在我们来体验一下manifest文件的作用,如果现在我们有一个Java应用程序打包在myapplication.Jar中, main class为com.example.myapp.MyAppMain,那么我们可以用以下的命令来运行

java -classpath myapplication.Jar 

com.example.myapp.MyAppMain

这显然太麻烦了,现在我们来创建自己的manifest文件,如下:

Manifest-Version: 1.0
Created-By: JDJ example
Main-Class: com.example.myapp.MyAppMain

这样我们就可以使用如下的命令来运行程序了:(明显简单多了,也不会造成无谓的拼写错误)

java -Jar myapplication.Jar

管理Jar的依赖资源

很少Java应用会仅仅只有一个Jar文件,一般还需要其他类库。比如我的应用程序用到了Sun 的 Javamail classes ,在classpath中我需要包含activation.Jar 和 mail.Jar,这样在运行程序时,相比上面的例子,我们要增加一些:

java -classpath mail.Jar:

activation.Jar -Jar myapplication.Jar

在不同的操作系统中,Jar包间的分隔符也不一样,在UNIX用“:”,在window中使用 “;”,这样也不方便。同样,我们改写我们的manifest文件,如下:

Manifest-Version: 1.0
Created-By: JDJ example
Main-Class: com.example.myapp.MyAppMain
Class-Path: mail.Jar activation.Jar
加入了Class-Path: mail.Jar 
activation.Jar,用空格分隔两个Jar包

这样我们仍然可以使用和上例中相同的命令来执行该程序:

java -Jar myapplication.Jar

Class-Path属性中包含了用空格分隔的Jar文件,在这些Jar文件名中要对特定的字符使用逃逸符,比如空格,要表示成"%20",在路径的表示中,都采用“/”来分隔目录,无论是在什么操作系统中,(即使在window中),而且这里用的是相对路径(相对于本身的Jar文件):

Manifest-Version: 1.0
Created-By: JDJ example
Main-Class: com.example.myapp.MyAppMain
Class-Path: ext/mail.Jar ext/activation.Jar 
Multiple Main Classes(多主类)

还有一种Multiple Main Classes情况,如果你的应用程序可能有命令行版本和GUI版本,或者一些不同的应用却共享很多相同的代码,这时你可能有多个Main Class,我们建议你采取这样的策略:把共享的类打成lib包,然后把不同的应用打成不同的包,分别标志主类:如下:

Manifest for myapplicationlib.Jar:
Manifest-Version: 1.0
Created-By: JDJ example
Class-Path: mail.Jar activation.Jar 
Manifest for myappconsole.Jar:
Manifest-Version: 1.0
Created-By: JDJ example
Class-Path: myapplicationlib.Jar
Main-Class: com.example.myapp.MyAppMain 
Manifest for myappadmin.Jar:
Manifest-Version: 1.0
Created-By: JDJ example
Class-Path: myapplicationlib.Jar
Main-Class: com.example.myapp.MyAdminTool 
在myappconsole.Jar 
和 
myappadmin.Jar的manifest
文件中分别注明各自的 Main Class
Package Versioning

完成发布后,如果使用者想了解,哪些代码是谁的?目前是什么版本?使用什么版本的类库?解决的方法很多,manifest提供了一个较好的方法,你可以在manifest文件中描述每一个包的信息。

Java秉承了实现说明与描述分离的原则,package的描述定义了package是什么,实现说明 定义了谁提供了描述的实现,描述和实现包含名、版本号和提供者。要得到这些信息,可以查看JVM的系统属性(使用 java.lang.System.getProperty() )

在manifest文件中,我可以为每个package定义描述和实现版本,声明名字,并加入描述属性和实现属性,这些属性是:

Specification-Title 
Specification-Version 
Specification-Vendor 
Implementation-Title 
Implementation-Version 
Implementation-Vendor

当要提供一个类库或编程接口时,描述信息显得是很重要,见以下范例:

Manifest-Version: 1.0
Created-By: JDJ example
Class-Path: mail.Jar activation.Jar 
Name: com/example/myapp/
Specification-Title: MyApp
Specification-Version: 2.4
Specification-Vendor: example.com
Implementation-Title: com.example.myapp
Implementation-Version: 2002-03-05-A
Implementation-Vendor: example.com

Package Version 查询

在manifest文件中加入package描述后,就可以使用Java提供的java.lang.Package class进行Package 的信息查询,这里列举3个最基本的获取package object的方法

1.Package.getPackages():返回系统中所有定义的package列表

2.Package.getPackage(String packagename):按名返回package

3.Class.getPackage():返回给定class所在的package

使用者这方法就可以动态的获取package信息。

需要注意的是如果给定的package中没有class被加载,则也无法获得package对象。

Manifest 技巧

1、总是以Manifest-Version属性开头

2、每行最长72个字符,如果超过的化,采用续行

3、确认每行都以回车结束,否则改行将会被忽略

4、如果Class-Path 中的存在路径,使用"/"分隔目录,与平台无关

5、使用空行分隔主属性和package属性

6、使用"/"而不是"."来分隔package 和class ,比如 com/example/myapp/

7、class 要以.class结尾,package 要以 / 结尾

(T117)


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· Java数据库编程中的几个常用技巧 (12-08) · 看沧海变桑田 Web2.0中AJAX应用探讨(二) (12-08)
· 看沧海变桑田 Web2.0中AJAX应用探讨(一) (12-08) · 详细讲解Quartz如何从入门到精通 (12-07)
· Jakarta Commons中隐藏的宝贝-第一部分 (12-07) · 如何来提高您的J2EE项目的质量 (12-07)
· 用Java实现自动在数据库表中生成ID号 (12-07) · Java组件开发要决:一个概念框架 (12-07)
· 用 Struts 实现动态单选按钮 (12-06) · Java对战.NET,战争与和平的游戏 (12-06)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
  赛迪推荐  
  手机·资费 ·新品·导购·评测·手机资费·宽带
手机搜索  诺基亚 N73 MOTO Z6
  IT产品 ·笔记本·台式机·服务器·打印·投影
IT产品搜索 
  IT技术 ·开发·网管·安全·数据库·操作系统
  信息化 ·热点·专题·访谈·周刊·方案案例
· 信息化市场百家争鸣 SaaS深陷争议“泥潭”
· 提高管理水平 "两栖"CIO应具备的六大能力
· 国产ITIL运维先行者 四大厂商角力BI市场
· 金融行业GSN专题解决方案 企业网解决方案
  IT博客 ·曾剑秋·项立刚·Java学习·网管
  IT技术论坛 ·开发·网管·安全·数据库·系统