今天我们来聊聊jar
包。作为Java
程序员,日常工作就是打自己的jar
包和学别人的jar
包。
什么是jar包?
jar包
, Java Archive File
,顾名思义,它与 Java
息息相关的,是 Java
的一种文档格式,同时也是一种与平台无关的文件格式,可将多个文件合成一个jar
文件。
大伙会觉得它与zip包
非常类似,确实,确切地说,它就是 zip 包
。jar
与 zip
唯一的区别就只是在 jar
文件的META-INF
目录下多包含了一个 MANIFEST.MF
文件作为jar里面的"详情单",这个文件里包含了该Jar
包的版本、创建人和类搜索路径Class-Path
等信息,当然如果是可执行Jar
包(包含main()
方法),还会包含Main-Class
属性,表明main()
方法入口。其中较为重要的Class-Path
和Main-Class
。
此外,由于jar
包主要是对.class
文件进行打包,而java
编译生成的.class
文件是跨平台的,这就意味着jar
包也是跨平台的,这是jar
包的优势。
小伙伴们在平时编写代码的时候,可以把自己代码中的通用部分分离出来,积累一些通用的工具类,将其逐渐模块化,最后打成jar
包供自己在别的项目或者模块中使用。同时可以不断完善jar
包里面的内容,将其做得更加容易理解和使用。
因此,将自己写好的通用工具类或者框架分离出来,打成jar
包供自己或他人调用,不仅能够提升自己的编程水准,同时也能扩宽整个Java
生态圈,这也是Java
如此受欢迎的原因之一。
如何打jar包?
现在,我们来试着打包我们自己写好的java
源文件。
记得最早接触的一个第三方jar
包,是 mysql-connector-java-8.0.24.jar
,即Java
中著名的jdbc
驱动包
虽然这个驱动包使用起来非常方便,但是仍然有许多重复的代码需要我们去编写,所以一些主流的Java
框架会对其进行再次封装,比如SpringBoot
框架中,我们只需要填入数据库地址,用户名,密码等基本信息即可访问我们的数据库,下面,我们就尝试着对这个驱动包进行二次封装,并把它打包成jar
包,以下是我们的目标:
- 向用户开放一个主构造方法:
ConnectMysql(String url, String username, String password)
用于连接mysql
数据库。 - 用户只需调用
insert(), delete(), update(), select()
四个方法即可实现对于数据库的 增 删 改 查 四个操作。
二次封装
首先对jdbc
驱动包做二次封装,代码如下:
1 | package com.sixibiheye.mysql; |
记住 ConnectMysql
这个类放在了 com.sixibiheye.mysql
包里,现在,我们尝试着将其打包成jar
包。同样的,我们不借助任何第三方工具,采用最原生的java
命令来打jar
包。下面的教程假设小伙伴们已经配置好了java的基础环境。(Mac
用户与Windows
用户均可用)
制作jar
包清单材料
首先,我们来看看,打包成一个jar
包需要哪些东西:
我们新建一个MakeJar
文件夹(文件夹名任意),在这个文件夹中,添加三个材料:
- 编译后的
.class
文件(如果有多个.class
文件且处于不同的包里,注意放到对应的包里) MANIFEST.MF
清单文件(待会解释)- 打
jar
包所依赖的jar
包(此例中由于使用到了jdbc
驱动包,故需要将其添加进去,此外,java
自带的jar
包无需添加进去,如java.sql.*
)
第一,三个材料大家容易理解,这里主要介绍一下MANIFEST.MF
清单文件, 清单文件用来指明我们打jar
包的一些基本信息,最重要的是主区(Main Section
)的四个属性:
Manifest-Version
版本号,如1.0
Create-By
创建者,一般格式:jdk
版本(开发者或公司) ,如 1.6.0_35(sum Microsystems Inc.)
,可以省略。
Main-Class
可执行jar
包(即包含main
方法)的入口类名,如果我们编写的多个类含有多个main
方法,此属性可指定调用jar
包的入口类的main
方法。如果编写的 ConnectMysql
类中无main()
方法,则Main-Class
属性可以省略。值得注意的是,属性值一定要包含类所在的包名,如:
Main-Class: com.sixibiheye.mysql.ConnectMysql
-
Class-Path
JVM
搜索依赖的jar
包的路径,三种情况: -
如果依赖的
jar
包就在当前路径,直接使用jar包名即可; -
如果依赖的
jar
包不在当前路径,使用全局路径; -
如果依赖的
jar
包在当前路径的子路径中,使用相对路径。
如果有多个依赖的jar
包,包与包之间用一个空格隔开即可。此处,我们所依赖的jar
包就在当前路径,所以直接写jar
包名即可。
当然清单文件中还可以添加一些其他内容,感兴趣的小伙伴们可以去查阅有关资料。
此例中,我们的MANIFEST.MF
清单文件长这样:
注意:属性与属性值之间有一个空格;最后一定要留出一空行,否则最后一行读取不到。
打jar
包
接下来,我们开始打包,Java
提供了 jar命令
用于打jar包。
打开我们的cmd
(控制台),将当前路径切换至MakeJar
,接着输入如下命令:
jar -cvfm mysql-connector-java.jar MANIFEST.MF -C ./ .
命令中,mysql-connector-java.jar
为生成的jar包的名称,MANIFEST.MF
表示使用指定此清单文件用于生成jar
包,“ ./
”和后面的“ .
”之间有一空格,控制参数c,v,f,m
的含义分别是:
- -c:即
create
,创建一个jar
包 - -v:即
view
,生成详细的报告并输出至标准设备 - -f:即
force
,指定生成的jar
包的名称 - -m:即
manifest.mf
清单文件,指定一个清单文件
末尾 “ -C
” 参数的含义是, 转到相应的目录下执行jar
命令,即相当于cd
到那个目录,然后不带“ -C
” 参数执行jar
命令。
图示如下:
如果输出类似上述信息,则表示打包成功。
在MakeJar
文件夹中,我们可以看到生成的 **mysql-connector-java.jar
**:
一个简单的jar
包就生成完毕了。
jar
包测试
我们来测试一下这个jar
包好不好使,在上述目录中,编写一个Test.java
类,代码如下:
1 | package com.sixibiheye.mysql; |
进入MakeJar
文件夹中,在命令行输入如下命令:
控制参数 “
-cp
” (即ClassPath
)告诉JVM
源文件编译运行时所依赖的jar
包的路径,路径的写法与之前清单文件中的Class-Path
类似。
可以看到,我们成功地获得了想要的数据。使用封装好的jar
包连接数据库并获得数据的代码量要少得多。这再一次体现出封装的优越性。