探究maven项目的打包方式

article/2025/9/19 14:41:27

目录

前言

概念

准备

打包方式

idea自带的maven工具

小包打包第一种方式

小包打包第二种方式

小包总结

大包打包

maven-compiler-plugin

依赖配置

打包测试

效果

maven-jar-plugin 和 maven-dependency-plugin

maven-jar-plugin

maven-dependency-plugin

依赖配置

效果

maven-assembly-plugin

缺点

依赖配置

效果

 两者的区别

 maven-shade-plugin

依赖配置 

效果

两种第三方插件打包方式的总结

前言

        现在都是使用idea中maven插件来打包项目,因此此文章将基于idea中的maven插件打包。

概念

打包分为小包和大包两种概念:

        小包:只打包我们写的代码,不打包代码依赖的其他jar包。

        大包:打包项目本身的代码以及项目所依赖的其他jar包。

因此,如果我们的项目代码只需要被别的代码引用,也就是不需要启动类去运行,那么打包成小包即可,如果我们的项目需要独立的运行,需要启动类去运行,那么就需要打包成大包。

准备

我们先创建一个maven项目,创建一个启动类,随便引入一个其他依赖。

启动类

pom文件

打包方式

idea自带的maven工具

        首先使用idea中自带的maven工具打包,idea的maven工具也能打大包和小包。

小包打包第一种方式

        小包打包直接运行maven中的package即可。

 可以看到target目录下生成了jar包

 查看生成的jar包

可以看到只有我们项目的代码,引入的依赖并没有被一起打包

这里也就不测试能不能通过命令java -jar *.jar 去运行jar包了,因为这是小包,根据小包的作用,我们是并不需要去运行。这里我可以告诉你,并不能运行,因为我们打包的时候并没有去指定启动类的路径,也就是在META-INF目录下的MANIFEST.MF文件中指定启动类。 

小包打包第二种方式

        大包打包我们是需要指定启动类并且将其他依赖一起打包的。

 配置打包信息

 

配置完后,我们可以看到引入的依赖也在被打包的范围,同时如果我们不想打包某个jar包进来,可以在此面板选择删除,这样就不会一同被打包了。

然后去编译打包

 

 

 可以看到生成了out输出文件夹,并且引入的依赖也一同被打包到同个目录下了,但是还是没有合并成同一个jar,如果要运行的话,必须将依赖的jar放在同一个目录中才能正常运行。

 我们来查看以下生成的jar包

我们发现,打包的jar貌似比小包更简洁 ,而且也只有我们本身的java代码,没有MANIFTEST文件,没有的话肯定是无法运行的,因为里面记录启动类的路径以及依赖jar包的存放路径。

 很奇怪,我们的MANIFEST文件跑到这里了,并没有被一同打包。

 可以看到MANIFEST中已经生成了jar的存放路径和启动类的路径

原来,我们的这种打包方式必须要和打包插件共同使用,后面会介绍几种打包插件。

这样的打包方式也有解决方法,就是将我们打包的jar解压,将MANIFEST文件放进去再压缩,最后将压缩好的jar包和引入的jar包放在同一个目录中即可运行。

小包总结

从 上面的两种方式可以看出来,idea自带的打包方式,只能打包成小包,源码的部分只有项目本身的代码。这种 Jar 包就是所谓的 “小包”。

大包打包

从前面来看,打包打包需要使用到第三方插件,以下来介绍一些第三方的打包插件。

maven-compiler-plugin

maven-compiler-plugin是一个Maven插件,可以用来指定项目源码的 jdk 版本,编译后的 jdk 版本,以及编码格式。,单独的使用并不会打包成大包,还是会打成小包,因此一般用来与其他第三方的打包插件联合使用。

依赖配置

<build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --><source>1.8</source> <!-- 源代码使用的JDK版本 --><target>1.8</target> <!-- 需要生成的目标class文件的编译版本 --><encoding>UTF-8</encoding><!-- 字符集编码 --></configuration></plugin></plugins></build>

打包测试

效果

可以看到只有源码被打包而已。

maven-jar-plugin 和 maven-dependency-plugin

这两个插件是一起使用的,首先是不推荐使用这种,此种打包方式有一个比较明显的缺点:打包后会在 target 目录下生成 lib 目录(存放依赖 Jar)和项目 Jar。也就是说由于依赖都存在于 lib 目录中,所以要想运行 Jar 包,必须将 Jar 包和 lib 目录放在同一个路径下。

maven-jar-plugin

首先说 maven-jar-plugin 插件,它的思想就是:指定启动类、指定依赖包相对于项目最终 Jar 包所在的路径、给 MANIFEST.MF 文件添加 Class-Path 属性(运行项目 Jar 包时会根据 Class-Path 属性来找到其他依赖 Jar 包的路径),因此这个插件就是个配置 MANIFEST.MF 文件的插件。

maven-dependency-plugin

这个插件才是打包项目的其他依赖,因此这个必须配合上面的插件使用,两者缺一不可。

依赖配置

<build><!-- 项目最终打包成的名字 --><finalName>community</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifest><!-- 会在 MANIFEST.MF 中生成 Class-Path 项 --><!-- 系统会根据 Class-Path 项配置的路径加载依赖 --><addClasspath>true</addClasspath><!-- 指定依赖包所在目录,相对于项目最终 Jar 包的路径 --><classpathPrefix>lib/</classpathPrefix><!-- 指定 MainClass --><mainClass>com.ronz.community.CommunityApplication</mainClass></manifest></archive></configuration></plugin><!-- 配置依赖包 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><!-- 相当于执行 mvn 命令,将依赖打包到指定目录 --><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><!--将依赖打包至 target 下的 lib 目录--><outputDirectory>${project.build.directory}/lib</outputDirectory></configuration></execution></executions></plugin></plugins>
</build>

效果

 所以说想要运行项目,必须将lib和源码jar包放在同一个目录下才行,这样显然是不太方便的。

maven-assembly-plugin

使用 maven-assembly-plugin 插件打出来的包只有一个 Jar 包,这个 Jar 包中包含了项目代码以及依赖的代码。也就意味着此种方式打出来的 Jar 包可以直接通过 java -jar xxx.jar 的命令来运行。而且我们可以联合maven-compiler-plugin插件来使用。

缺点

maven-assembly-plugin 同名类覆盖时会出现问题。

依赖配置

    <build><!-- 项目最终打包成的名字 --><finalName>test</finalName><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --><source>1.8</source> <!-- 源代码使用的JDK版本 --><target>1.8</target> <!-- 需要生成的目标class文件的编译版本 --><encoding>UTF-8</encoding><!-- 字符集编码 --></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><configuration><archive><!-- 指定启动类 --><manifest><mainClass>com.cw.HelloStart</mainClass></manifest></archive><!-- 描述后缀 --><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><!-- 相当于在执行 package 打包时,在后面加上 assembly:single  --><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>

效果

 两者的区别

test-jar-with-dependencies.jar

test.jar

 明显可以看到test-jar-with-dependencies.jar才是我们需要的。

 maven-shade-plugin

根据 Maven 的官方文档介绍,maven-shade-plugin 是一个强大的打包插件。它同样可以将项目的依赖以及项目的源码打包成一个可执行 Jar 包。

依赖配置 

    <build><!-- 项目最终打包成的名字 --><finalName>test</finalName><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --><source>1.8</source> <!-- 源代码使用的JDK版本 --><target>1.8</target> <!-- 需要生成的目标class文件的编译版本 --><encoding>UTF-8</encoding><!-- 字符集编码 --></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><transformers><!-- 指定启动类 --><transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>com.cw.HelloStart</mainClass></transformer><!-- 下面的配置仅针对存在同名资源文件的情况,如没有则不用配置--><!-- 有些项目包可能会包含同文件名的资源文件(例如属性文件)--><!-- 为避免覆盖,可以将它们的内容合并到一个文件中 --><transformerimplementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"><resource>META-INF/spring.handlers</resource></transformer><transformerimplementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"><resource>META-INF/spring.schemas</resource></transformer></transformers></configuration></execution></executions></plugin></plugins></build>

效果

两种第三方插件打包方式的总结

使用第二种方式的 assembly 打包出来的 Jar 包多多少少有些问题,但是使用第三种方式打包出来的 Jar 包一般都是可用的。所以在将项目打包为大包时,还是推荐使用第三种打包的方式。

如果是大数据项目中,我们日常使用比较多的是maven-assembly-plugin插件,例如:大数据项目中往往有很多shell脚本、SQL脚本、.properties.xml配置项等,采用assembly插件可以让输出的结构清晰而标准化。


http://chatgpt.dhexx.cn/article/lZrGFZiT.shtml

相关文章

6.Maven打包操作

对于企业级项目&#xff0c;无论是进行本地测试&#xff0c;还是测试环境测试以及最终的项目上线&#xff0c;都会涉及项目的打包操作。对于每个环境下的项目打包&#xff0c;对应的项目所需要的配置资源都会有所区别&#xff0c;实现打包的方式有很多种&#xff0c;可以通过an…

Maven 的打包方式

一、前言 刚开始实习不到一个月的时候&#xff0c;从师兄手中接手了团队的项目&#xff0c;当时第一次听到了 “大包”、“小包” 的概念&#xff0c;只见师兄一顿操作&#xff0c;使用 Maven 将项目进行了打包。当时不太理解&#xff0c;只是记得两点&#xff1a; 如果想让项…

Java中main()方法的使用

一、main()方法的使用说明 main()方法作为程序的入口。main()方法也是一个普通的静态方法。main()方法可以作为我们与控制台交互的方式&#xff08;之前&#xff1a;使用Scanner&#xff09;。 二、main()方法使用举例 MainDemo.java public class MainDemo {public static…

JAVA中main方法如何执行。

public class Test{public static void main(String[] args){System.out.println("hello world");}} 上述就是java代码中的一段简单的main函数的代码&#xff0c;代码执行后输出结果为&#xff1a;hello world main函数&#xff1a; 在java中main函数是一个特殊的…

深入理解Java的main方法

一、简单介绍 在我们的Java程序中都会出现一个名称为main的方法&#xff0c;我们发现没有这个方法我们的程序就无法运行。 其实任何一个Java程序的运行入口都是这个main方法&#xff0c;也就是说&#xff0c;程序在运行的时候&#xff0c;第一个执行的方法就是main()方法&#…

main方法详解

学习Java有一段时间了&#xff0c;一直没用过博客来写写自己在学习过程中遇到的问题和学习心得&#xff0c;看到别人在诸如博客这样的社区写一些总结觉得挺好的。索性&#xff0c;今天开始自己也用起博客记录学习。一来呢&#xff0c;能更好的总结学习知识。二来&#xff0c;有…

java中main方法的作用

main方法是我们学习Java语言学习的第一个方法&#xff0c;也是每个java使用者最熟悉的方法,每个Java应用程序都必须有且仅有一个main方法。在eclipse里可以使用输入main&#xff0c;在按住Alt/的方式快速创建main方法。可以说main方法是最简单的方法&#xff0c;因为main方法几…

Java中的main()方法如何运用?

​ 在Java中&#xff0c;main()方法是Java应用程序的入口方法&#xff0c;也就是说&#xff0c;程序在运行的时候&#xff0c;第一个执行的方法就是main()方法&#xff0c;这个方法和其他的方法有很大的不同&#xff0c;比如方法的名字必须是main&#xff0c;方法必须是public …

解析java中的main方法

解析java中的main方法 1.一个java源文件(.java文件)可以有多个class类 1.1 分析 例如下面代码编译时不会报错,只不过编译后会生成多个对应的class类文件 其中有多少个类就生成class类文件 1.2 示例代码 class B{} public class Practice {public static void main(String[…

Java main方法_解释Java中的main方法,及其作用_一个java文件中可包含多个main方法

public static void main(String[] args) {}或者 public static void main(String args[]) {}main方法是我们学习Java语言学习的第一个方法&#xff0c;也是每个java使用者最熟悉的方法,每个Java应用程序都必须有且仅有一个main方法。在eclipse里可以使用输入main&#xff0c;…

Java 中的main方法原理介绍。

//深入了解main方法 // 解释main方法的形式为什么是这样写的&#xff1f; // public static void main(String[] args) // 问题1&#xff1a;是谁调用main方法&#xff1f; // java虚拟机调用main方法&#xff0c;所以main的访问权限是public // 问题2&#xff1a;为什么是st…

main()方法java

main()方法java 实际上&#xff0c;程序中的main()方法不是必须要放在唯一的一个公共类中的&#xff0c;它可以放在其它类当中&#xff0c;但正常情况下这样做会报错&#xff0c;这是为什么呢&#xff1f;是因为程序在执行的过程中第一步是调用&#xff1a; 文件名.main() 正常…

Java--main()方法

文章目录 一、main()方法使用二、mian()方法调用 一、main()方法使用 1、访问控制权限是公有的&#xff08;public&#xff09; 2、main() 方法是静态的。如果要在 main() 方法中调用本类中的其他方法&#xff0c;则该方法也必须是静态的&#xff0c;否则需要先创建本类的实例…

java学习之main方法

目录 一、main方法的注意事项 二、在IDEA中传入参数 一、main方法的注意事项 形式&#xff1a;public static void main(String[] args){}&#xff0c;main方法是一个静态方法&#xff0c;访问修饰符是&#xff1a;public&#xff0c;形参是String数组 args 注意事项&#xf…

深入理解 main 方法

目录 深入理解 main 方法 public static void main(String[] args) { }注意事项 深入理解 main 方法 public static void main(String[] args) { } 在Java 中&#xff0c;main() 方法是 Java 应用程序的入口方法&#xff0c;程序在运行的时候&#xff0c;第一个执行的方法就是…

java中main()方法详解

package javase2; /** public static void main(String [] args){....}* pblic&#xff1a;公共的&#xff0c;访问权限最大&#xff0c;由于main要被jvm调用&#xff0c;所以要权限够大* static&#xff1a;静态不需要创建对象&#xff0c;方便jvm调用* void&#xff1a;方法的…

Java中的main方法

main方法是java应用程序中的一个入口&#xff0c;它被声明为公有静态方法&#xff0c;参数是一个字符串数组&#xff0c;返回值为void类型。 一个java文件可以有无数个main方法&#xff0c;但是一个类中只能有一个main方法&#xff0c;当想要运行不同的main时&#xff0c;可以…

Java的main方法

Java的main方法 我们在编写程序的时候经常使用到main方法&#xff0c;但是main方法具体是什么意思呢&#xff1f; 1、main方法的调用者是java虚拟机。 2、因为调用者是java虚拟机&#xff0c;java虚拟机不在该类中也不在该类所在的包中更不是该类的子类&#xff0c;所以main函数…

Java基础——main方法

深入理解main方法 解释main方法的形式&#xff1a;public static void main(String [] args){} main方法是由java虚拟机调用的。java虚拟机需要调用类的main()方法&#xff0c;所以该方法的访问权限必须是public。Java虚拟机在执行main()方法时不必创建对象&#xff0c;所以该…

详解Java中的main方法

main方法格式定义 public: main方法启动时由JVM进行加载&#xff0c;public的可访问权限是最高的&#xff0c;所有需要声明为public;static: 方法的调用要么是通过对象&#xff0c;要么是通过类&#xff0c;而main方法的话&#xff0c;因为是由虚拟机调用的&#xff0c;所以无…