当前位置: 代码网 > it编程>编程语言>Java > 解读maven项目的打包方式

解读maven项目的打包方式

2024年08月12日 Java 我要评论
前言现在都是使用idea中maven插件来打包项目,因此此文章将基于idea中的maven插件打包。概念打包分为小包和大包两种概念:小包:只打包我们写的代码,不打包代码依赖的其他jar包。大包:打包项

前言

现在都是使用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>
                                <!-- 指定启动类 -->
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.manifestresourcetransformer">
                                    <mainclass>com.cw.hellostart</mainclass>
                                </transformer>
 
                                <!-- 下面的配置仅针对存在同名资源文件的情况,如没有则不用配置-->
                                <!-- 有些项目包可能会包含同文件名的资源文件(例如属性文件)-->
                                <!-- 为避免覆盖,可以将它们的内容合并到一个文件中 -->
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.appendingtransformer">
                                    <resource>meta-inf/spring.handlers</resource>
                                </transformer>
                                <transformer
                                        implementation="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插件可以让输出的结构清晰而标准化。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com