SpringBoot程序打包失败(.jar中没有主清单属性)

 更新时间:2023年06月28日 09:49:43   作者:小小孙十八  
在学习SpringBoot,打包SpringBoot程序后,在cmd运行出现了 某某某.jar中没有注清单属性,本文就来介绍一下原因以及解决方法,感兴趣的可以了解一下

最近在学习SpringBoot,打包SpringBoot程序后,在cmd运行出现了 某某某.jar中没有注清单属性 。

image-20211201094223991.png

我当时也是很懵逼,就去万能的互联网寻求帮助,累计找了大概十几篇文章吧,最后总算是在一个网友的评论中得到了答案,在此先感谢那位留下评论的热心网友。

我的错误

说明一下,我的SpringBoot模板是基于aliyun镜像创建的。

在默认给出的配置的环境下,pom.xml中是有spring-boot-maven-plugin这个依赖的,所以可以先排除没有这个依赖的说法。

我用maven打包后,只给出了一个内存较小的jar文件,运行这个文件,就会出现上述没有主属性清单的错误,至于这个jar文件为何会出现这个错误,我会在文章的下面讲。

在看到这位热心网友的评论时,我也不明白是因为什么,根据TA的说法,我更改的默认的配置,唉,成了,在打包后出现了两个jar。

image-20211201095610270.png

运行那个内存占用较大的jar,运行成功(喜)。而为什么要运行占用内存较大的呢,也在后文做解释。

解决方法

我的解决方案:

对pom.xml文件做如下修改

<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-compiler-plugin</artifactId>
                   <version>3.8.1</version>
                   <configuration>
                       <source>1.8</source>
                       <target>1.8</target>
                       <encoding>UTF-8</encoding>
                   </configuration>
		</plugin>
		<plugin>
			<groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-maven-plugin</artifactId>
                   <version>${spring-boot.version}</version>
                   <!-- 把这里给删除就可以打包成功 -->
                   <!--<configuration>
                       <mainClass>com.sun.SSMPApplication</mainClass>
                       <skip>true</skip>
                   </configuration>-->
                   <executions>
                       <execution>
                           <id>repackage</id>
                           <goals>
                               <goal>repackage</goal>
                           </goals>
                       </execution>
                   </executions>
         </plugin>
	</plugins>
</build>

错误分析

要想搞清楚这个问题就要说说.jar文件的工作机制了,知道了这个东西就知道如何避免此类问题的发生了。

搞java开发平时会接触很多jar包,比如mysql的驱动jar包,而上面我们打包程序后得到的也是一个jar文件。这个时候如果你使用上面的java -jar指令去执行mysql的驱动jar包就会出现上述不可执行的现象。

而SpringBoot项目为什么能执行呢?其实是因为打包方式不一样。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

我们分别开启这段配置和注释掉这段配置分别执行两次打包,然后观察两次打包后的程序包的差别,共有3处比较明显的特征:

1、打包后文件的大小不同

2、打包后所包含的内容不同

3、打包程序中个别文件内容不同

大小不同

先看第一个现象,文件大小不同。带有配置时打包生成的程序包大小如下:

image-20211201095610270.png

包含内容不同

不难看出,带有配置的程序包体积比不带配置的大了30倍,看看里面的内容有什么区别。

image-20211201101541267.png

image-20211201101652868.png

发现内容也完全不一样,仅有一个目录是一样的,叫做META-INF。打开容量大的程序包中的BOOT-INF目录下的classes目录,发现其中的内容居然和容量小的程序包中的内容完全一样。

image-20211201101805569.png

image-20211201101652868.png

原来大的程序包中除了包含小的程序包中的内容,还有别的东西。回到BOOT-INF目录下,打开lib目录,里面显示了很多个jar文件。

image-20211201102025791.png

这些jar文件都是我们制作这个工程时导入的坐标对应的文件。SpringBoot程序为了让自己打包生成的程序可以独立运行,不仅将项目中自己开发的内容进行了打包,还把当前工程运行需要使用的jar包全部打包进来了。这样做就是为了可以独立运行。不依赖程序包外部的任何资源可以独立运行当前程序。这也是为什么大的程序包容量是小的程序包容量的30倍的主要原因。

再看看大程序包还有什么不同之处,在最外层目录包含一个org目录,进入此目录,目录名是org\springframework\boot\loader,在里面可以找到一个JarLauncher.class的文件。再看这套目录名,明显是一个Spring的目录名。

个别文件内容不同

回到两个程序包的最外层目录,查看名称相同的文件夹META-INF下都有一个叫做MANIFEST.MF的文件,但是大小不同,打开文件,比较内容区别

小容量文件的MANIFEST.MF

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: 名字
Created-By: Apache Maven 3.8.1
Build-Jdk: 1.8.0_201

大容量文件的MANIFEST.MF

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Archiver-Version: Plexus Archiver
Built-By: 名字
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: com.sun.SSMPApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.6.13
Created-By: Apache Maven 3.8.1
Build-Jdk: 1.8.0_201
Main-Class: org.springframework.boot.loader.JarLauncher

大文件中明显比小文件中多了几行信息,其中最后一行信息是Main-Class: org.springframework.boot.loader.JarLauncher。即如果使用java -jar执行此程序包,将执行Main-Class属性配置的类,这个类恰巧就是前面看到的那个文件。原来SpringBoot打包程序中出现Spring框架的东西是为这里服务的。而这个org.springframework.boot.loader.JarLauncher类内部要查找Start-Class属性中配置的类,并执行对应的类。这个属性在当前配置中也存在,对应的就是我们的引导类类名。

  • SpringBoot程序添加配置后会打出一个特殊的包,包含Spring框架部分功能,原始工程内容,原始工程依赖的jar包
  • 首先读取MANIFEST.MF文件中的Main-Class属性,用来标记执行java -jar命令后运行的类
  • JarLauncher类执行时会找到Start-Class属性,也就是启动类类名
  • 运行启动类时会运行当前工程的内容
  • 运行当前工程时会使用依赖的jar包,从lib目录中查找

SpringBoot打出来了包为了能够独立运行,将所有需要使用的资源全部都添加到了这个包里。这就是为什么这个jar包能独立运行的原因。

总结

再来看之前的报错信息:

image-20211201094223991.png

由于打包时没有使用那段配置,结果打包后形成了一个普通的jar包,在MANIFEST.MF文件中也就没有了Main-Class对应的属性了,所以运行时提示找不到主清单属性,这就是报错的原因。

到此这篇关于SpringBoot程序打包失败(.jar中没有主清单属性)的文章就介绍到这了,更多相关SpringBoot程序打包失败内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot如何获取上下文ApplicationContext

    Springboot如何获取上下文ApplicationContext

    这篇文章主要介绍了Springboot如何获取上下文ApplicationContext,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Java线程池并发执行多个任务方式

    Java线程池并发执行多个任务方式

    这篇文章主要介绍了Java线程池并发执行多个任务方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Java ThreadLocal的设计理念与作用

    Java ThreadLocal的设计理念与作用

    这篇文章主要介绍了Java ThreadLocal的设计理念与作用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • JAVA中数组从小到大排序的2种方法实例

    JAVA中数组从小到大排序的2种方法实例

    JAVA中在运用数组进行排序功能时一般有多种解决方案,下面这篇文章主要给大家介绍了关于JAVA中数组从小到大排序的2种方法,文中都给出了详细的实例代码,需要的朋友可以参考下
    2023-03-03
  • Java 基础--Arrays工具类详解

    Java 基础--Arrays工具类详解

    这篇文章主要介绍了Java Arrays工具类用法,结合实例形式分析了java Arrays工具类针对数组元素修改、复制、排序等操作使用技巧与相关注意事项,需要的朋友可以参考下
    2021-09-09
  • 在zuulFilter中注入bean失败的解决方案

    在zuulFilter中注入bean失败的解决方案

    这篇文章主要介绍了在zuulFilter中注入bean失败的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java中的transient关键字介绍

    Java中的transient关键字介绍

    这篇文章主要介绍了Java中的transient关键字介绍,需要的朋友可以参考下
    2015-03-03
  • Spring Boot+Aop记录用户操作日志实战记录

    Spring Boot+Aop记录用户操作日志实战记录

    在Spring框架中使用AOP配合自定义注解可以方便的实现用户操作的监控,下面这篇文章主要给大家介绍了关于Spring Boot+Aop记录用户操作日志实战的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-04-04
  • java简易文本分割器实现代码

    java简易文本分割器实现代码

    这篇文章主要为大家详细介绍了java简易文本分割器的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • 2022年最新java 8 ( jdk1.8u321)安装图文教程

    2022年最新java 8 ( jdk1.8u321)安装图文教程

    这篇文章主要介绍了2022年最新java 8 ( jdk1.8u321)安装图文教程,截止2022年1月,官方出的jdk1.8目前已更新到8u321的版本,本文通过图文并茂的形式给大家介绍安装过程,需要的朋友可以参考下
    2022-08-08

最新评论