700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > eclipse打包成jar_Spring Boot 打包成的可执行 jar 为什么不能被其他项目依赖?

eclipse打包成jar_Spring Boot 打包成的可执行 jar 为什么不能被其他项目依赖?

时间:2019-09-09 02:03:28

相关推荐

eclipse打包成jar_Spring Boot 打包成的可执行 jar  为什么不能被其他项目依赖?

前两天被人问到这样一个问题:

“松哥,为什么我的 Spring Boot 项目打包成的 jar ,被其他项目依赖之后,总是报找不到类的错误?”

大伙有这样的疑问,就是因为还没搞清楚可执行 jar 和普通 jar 到底有什么区别?今天松哥就和大家来聊一聊这个问题。

多了一个插件

Spring Boot 中默认打包成的 jar 叫做 可执行 jar,这种 jar 不同于普通的 jar,普通的 jar 不可以通过java-jar xxx.jar命令执行,普通的jar主要是被其他应用依赖,SpringBoot打成的jar可以执行,但是不可以被其他的应用所依赖,即使强制依赖,也无法获取里边的类。但是可执行 jar 并不是 Spring Boot 独有的,Java 工程本身就可以打包成可执行 jar 。

有的小伙伴可能就有疑问了,既然同样是执行mvnpackage命令进行项目打包,为什么 Spring Boot 项目就打成了可执行 jar ,而普通项目则打包成了不可执行 jar 呢?

这我们就不得不提 Spring Boot 项目中一个默认的插件配置spring-boot-maven-plugin,这个打包插件存在 5 个方面的功能,从插件命令就可以看出:

五个功能分别是:

build-info:生成项目的构建信息文件 build-info.propertiesrepackage:这个是默认 goal,在mvnpackage执行之后,这个命令再次打包生成可执行的 jar,同时将mvnpackage生成的 jar 重命名为*.originrun:这个可以用来运行 Spring Boot 应用start:这个在mvn integration-test阶段,进行SpringBoot应用生命周期的管理stop:这个在mvn integration-test阶段,进行SpringBoot应用生命周期的管理

这里功能,默认情况下使用就是 repackage 功能,其他功能要使用,则需要开发者显式配置。

打包

repackage 功能的 作用,就是在打包的时候,多做一点额外的事情:

首先mvnpackage命令 对项目进行打包,打成一个jar,这个jar就是一个普通的jar,可以被其他项目依赖,但是不可以被执行repackage命令,对第一步 打包成的jar进行再次打包,将之打成一个 可执行jar,通过将第一步打成的jar重命名为*.original文件

举个例子:

对任意一个 Spring Boot 项目进行打包,可以执行mvnpackage命令,也可以直接在IDEA中点击package,如下 :

打包成功之后,target中的文件如下:

这里有两个文件,第一个restful-0.0.1-SNAPSHOT.jar表示打包成的可执行jar,第二个restful-0.0.1-SNAPSHOT.jar.original则是在打包过程中 ,被重命名的jar,这是一个不可执行jar,但是可以被其他项目依赖的jar。通过对这两个文件的解压,我们可以看出这两者之间的差异。

两种 jar 的比较

可执行jar解压之后,目录如下:

可以看到,可执行 jar 中,我们自己的代码是存在 于BOOT-INF/classes/目录下,另外,还有一个META-INF的目录,该目录下有一个MANIFEST.MF文件,打开该文件,内容如下:

Manifest-Version: 1.0Implementation-Title: restfulImplementation-Version: 0.0.1-SNAPSHOTStart-Class: org.javaboy.restful.RestfulApplicationSpring-Boot-Classes: BOOT-INF/classes/Spring-Boot-Lib: BOOT-INF/lib/Build-Jdk-Spec: 1.8Spring-Boot-Version: 2.1.6.RELEASECreated-By: Maven Archiver 3.4.0Main-Class: org.springframework.boot.loader.JarLauncher

可以看到,这里定义了一个Start-Class,这就是可执行jar的入口类,Spring-Boot-Classes表示我们自己代码编译后的位置,Spring-Boot-Lib则表示项目依赖的jar的位置。

换句话说,如果自己要打一个可执行jar包的话,除了添加相关依赖之外,还需要配置META-INF/MANIFEST.MF文件。

这是可执行 jar 的结构,那么不可执行 jar 的结构呢?

我们首先将默认的后缀.original除去,然后给文件重命名,重命名完成,进行解压:

解压后可以看到,不可执行jar根目录就相当于我们的classpath,解压之后,直接就能看到我们的代码,它也有META-INF/MANIFEST.MF文件,但是文件中没有定义启动类等。

Manifest-Version: 1.0Implementation-Title: restfulImplementation-Version: 0.0.1-SNAPSHOTBuild-Jdk-Spec: 1.8Created-By: Maven Archiver 3.4.0

注意

这个不可以执行jar也没有将项目的依赖打包进来。

从这里我们就可以看出,两个jar,虽然都是jar包,但是内部结构是完全不同的,因此一个可以直接执行,另一个则可以被其他项目依赖。

一次打包两个 jar

一般来说,Spring Boot 直接打包成可执行jar就可以了,不建议将 Spring Boot 作为普通的jar被其他的项目所依赖。如果有这种需求,建议将被依赖的部分,单独抽出来做一个普通的Maven项目,然后在 Spring Boot 中引用这个Maven项目。

如果非要将 Spring Boot 打包成一个普通jar被其他项目依赖,技术上来说,也是可以的,给spring-boot-maven-plugin插件添加如下配置:

<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><classifier>exec</classifier></configuration></plugin></plugins></build>

配置的classifier表示可执行jar的名字,配置了这个之后,在插件执行repackage命令时,就不会给mvnpackage所打成的jar重命名了,所以,打包后的 jar 如下:

第一个 jar 表示可以被其他项目依赖的 jar ,第二个 jar 则表示一个可执行 jar。

好了,关于 Spring Boot 中 jar 的问题,我们就说这么多,有问题欢迎留言讨论。

原创:江南一点雨

出自:微信公众号“江南一点雨”

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。