Maven - 打包之争:Jar vs. Shade vs. Assembly

文章目录

  • Pre
  • 概述
  • Jar 打包方式_maven-jar-plugin
    • Overview
    • 使用
    • 官方文档
  • Shade 打包方式_maven-shade-plugin
    • Overview
    • 使用
      • 将部分jar包添加或排除
      • 将依赖jar包内部资源添加或排除
      • 自动将所有不使用的类排除
      • 将依赖的类重命名并打包进来 (隔离方案)
      • 修改包的后缀名
    • 官方文档
  • Assembly 打包方式_maven-assembly-plugin
    • Overview
    • 使用
    • 官方文档

在这里插入图片描述


Pre

Maven - 统一构建规范:Maven 插件管理最佳实践

在这里插入图片描述


概述

Maven 提供了多种打包方式,其中常见的包括三种:jar、shade、assembly。下面是它们的详细比较:

  1. Jar 打包方式:

    • 描述: 这是最常见的打包方式,它创建一个标准的Java JAR文件。
    • 优点: 简单直接,适用于大多数简单项目。
    • 缺点: 不能包含项目的依赖,如果项目有外部依赖,用户必须手动将它们添加到类路径中。
  2. Shade 打包方式:

    • 描述: Maven Shade插件允许创建一个可执行的JAR文件,其中包含所有依赖。
    • 优点: 生成一个独立的可执行JAR,无需用户手动添加依赖。
    • 缺点: 可能会导致JAR文件较大,不适合所有项目。
  3. Assembly 打包方式:

    • 描述: Maven Assembly插件提供了一种更灵活的打包方式,允许创建各种自定义分发包。
    • 优点: 可以根据项目的需要创建定制的分发包,非常灵活。
    • 缺点: 配置相对复杂,适用于需要高度定制化的项目。

总结 :

  • Jar方式适用于简单项目,但对于有依赖的项目需要手动处理依赖 ; 默认的打包方式,用来打普通的project JAR包;。
  • Shade方式生成可执行JAR,但可能导致文件较大; 用来打可执行jar包,也就是所谓的fat JAR包。
  • Assembly方式最灵活,可以根据项目需求创建定制分发包 ; 自定义的打包结构,也可以定制依赖项等。

Jar 打包方式_maven-jar-plugin

Overview

使用maven-jar-plugin插件, 默认的打包方式,用来打普通的project JAR包 .


使用

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.1.0</version><configuration><archive><manifest><!-- 指定入口函数 --><mainClass>类的全路径名称</mainClass><!-- 是否添加依赖的jar路径配置 --><addClasspath>true</addClasspath><!-- 依赖的jar包存放位置,和生成的jar放在同一级目录下 --><classpathPrefix>lib/</classpathPrefix></manifest></archive><!-- 不打包com.artisan.excludes下面的所有类 --><excludes>com/artisan/excludes/*</excludes></configuration></plugin></plugins>
</build>

上面配置使用这个 jar包的时候就需要在它同一级的创建一个lib目录来存放。 可以使用includes或excludes选择的打包某些内容

官方文档

https://maven.apache.org/shared/maven-archiver/examples/classpath.html


Shade 打包方式_maven-shade-plugin

Overview

插件:使用maven-shade-plugin插件

maven-shade-plugin提供了两大基本功能:

  • 将依赖的jar包打包到当前jar包(常规打包是不会将所依赖jar包打进来的);
  • 对依赖的jar包进行重命名(用于类的隔离);

使用

maven-shade-plugin 只存在一个goal shade:shade,需要将其绑定到 phase package 上

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.1.1</version><configuration><!-- put your configurations here --></configuration><executions><execution><phase>package</phase><goals><goal>shade</goal></goals></execution></executions></plugin></plugins>
</build>

然后在当前pom文件所在路径下,执行打包命令:mvn clean package


将部分jar包添加或排除

<project>...<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.1.1</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><artifactSet><excludes><exclude>jmock:*</exclude><exclude>*:xml-apis</exclude><exclude>org.apache.maven:lib:tests</exclude><exclude>log4j:log4j:jar:</exclude></excludes><includes><include>junit:junit</include></includes></artifactSet></configuration></execution></executions></plugin></plugins></build>...
</project>
  • jar包以groupId:artifactId[[:type]:classifier]的形式表示
  • 1.3版本后插件支持通配符 ‘*’ and ‘?’

将依赖jar包内部资源添加或排除

<project>...<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.1.1</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><filters><filter><artifact>junit:junit</artifact><includes><include>junit/framework/**</include><include>org/junit/**</include></includes><excludes><exclude>org/junit/experimental/**</exclude><exclude>org/junit/runners/**</exclude></excludes></filter><filter><artifact>*:*</artifact><excludes><exclude>META-INF/*.SF</exclude><exclude>META-INF/*.DSA</exclude><exclude>META-INF/*.RSA</exclude></excludes></filter></filters></configuration></execution></executions></plugin></plugins></build>...
</project>

自动将所有不使用的类排除

<project>...<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.1.1</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><minimizeJar>true</minimizeJar></configuration></execution></executions></plugin></plugins></build>...
</project>

将依赖的类重命名并打包进来 (隔离方案)

<project>...<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.1.1</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><relocations><relocation><pattern>org.codehaus.plexus.util</pattern><shadedPattern>org.shaded.plexus.util</shadedPattern><excludes><exclude>org.codehaus.plexus.util.xml.Xpp3Dom</exclude><exclude>org.codehaus.plexus.util.xml.pull.*</exclude></excludes></relocation></relocations></configuration></execution></executions></plugin></plugins></build>...
</project>

将“org.codehaus.plexus.util”重命名为“org.shaded.plexus.util”,原始jar包中的“org.codehaus.plexus.util.xml.Xpp3Dom”和“org.codehaus.plexus.util.xml.pull”不会被重命名到目的包中;


修改包的后缀名

默认会生成一个Jar包和一个以 “-shaded”为结尾的uber-jar包,可以通过配置来指定uber-jar的后缀名。

<project>...<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.1.1</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><shadedArtifactAttached>true</shadedArtifactAttached><shadedClassifierName>jackofall</shadedClassifierName> <!-- Any name that makes sense --></configuration></execution></executions></plugin></plugins></build>...
</project>

Invalid signature file digest for Manifest main attributes

原因:有些jar包生成时,会 使用jarsigner生成文件签名(完成性校验),分为两个文件存放在META-INF目录下:

a signature file, with a .SF extension;
a signature block file, with a .DSA, .RSA, or .EC extension;

需要在生成 uber-jar时,将这些排除掉,不再进行完成性校验,如下所示:

<configuration><filters><filter><artifact>*:*</artifact><excludes><exclude>META-INF/*.SF</exclude><exclude>META-INF/*.DSA</exclude><exclude>META-INF/*.RSA</exclude></excludes></filter></filters>
</configuration>

https://maven.apache.org/plugins/maven-shade-plugin/examples/attached-artifact.html


官方文档

https://maven.apache.org/plugins/maven-shade-plugin/examples/attached-artifact.html


Assembly 打包方式_maven-assembly-plugin

Overview

使用maven-assembly-plugin插件 。

日常使用比较多的是maven-assembly-plugin插件

例如:大数据项目中往往有很多shell脚本、SQL脚本、.properties及.xml配置项等,采用assembly插件可以让输出的结构清晰而标准化


使用

首先在pom文件添加以下内容:

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>${maven-assembly-plugin.version}<version><executions><execution><id>make-assembly</id><!-- 绑定到package生命周期 --><phase>package</phase><goals><!-- 只运行一次 --><goal>single</goal></goals></execution></executions><configuration><!-- 配置描述符文件 --><descriptor>src/main/assembly/assembly.xml</descriptor><!-- 也可以使用Maven预配置的描述符<descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs> --></configuration></plugin></plugins>
</build>

然后编写描述符文件:

<assembly><id>assembly</id><formats><format>tar.gz</format></formats><includeBaseDirectory>true</includeBaseDirectory><fileSets><fileSet><directory>src/main/bin</directory><includes><include>*.sh</include></includes><outputDirectory>bin</outputDirectory><fileMode>0755</fileMode></fileSet><fileSet><directory>src/main/conf</directory><outputDirectory>conf</outputDirectory></fileSet><fileSet><directory>src/main/sql</directory><includes><include>*.sql</include></includes><outputDirectory>sql</outputDirectory></fileSet><fileSet><directory>target/classes/</directory><includes><include>*.properties</include><include>*.xml</include><include>*.txt</include></includes><outputDirectory>conf</outputDirectory></fileSet></fileSets><files><file><source>target/${project.artifactId}-${project.version}.jar</source><outputDirectory>.</outputDirectory></file></files><dependencySets><dependencySet><unpack>false</unpack><scope>runtime</scope><outputDirectory>lib</outputDirectory></dependencySet></dependencySets>
</assembly>
字段解析
formats是assembly插件支持的打包文件格式,有zip、tar、tar.gz、tar.bz2、jar、war。可以同时定义多个formats。
id是添加到打包文件名的标识符,用来做后缀。比如说,如果按上面的配置,生成的文件就是artifactId-{artifactId}-artifactId-{version}-assembly.tar.gz
fileSets/fileSet用来设置一组文件在打包时的属性。
directory源目录的路径。
includes/excludes设定包含或排除哪些文件,支持通配符。
fileMode指定该目录下的文件属性,采用Unix八进制描述法,默认值是064。
outputDirectory生成目录的路径。
files/file与fileSets大致相同,不过是指定单个文件,并且还可以通过destName属性来设置与源文件不同的名称。
dependencySets/dependencySet用来设置工程依赖文件在打包时的属性,也与fileSets大致相同。
dependencySet-unpack布尔值,false表示将依赖以原来的JAR形式打包,true则表示将依赖解成*.class文件的目录结构打包。
dependencySet-scope表示符合哪个作用范围的依赖会被打包进去。compile与provided都不用管,一般是写runtime。

按照以上配置打包好后,将.tar.gz文件上传到服务器,解压之后就会得到bin、conf、lib等规范化的目录结构,十分方便。


官方文档

https://maven.apache.org/plugins/maven-assembly-plugin/examples/single/filtering-some-distribution-files.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/168080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ElasticSearch之cat component templates API

命令样例如下&#xff1a; curl -X GET "https://localhost:9200/_cat/component_templates?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; name …

Qt/QML编程学习之心得:一个QML工程的学习笔记(十)

前言: 到底什么是Qt Quick呢?因为Qt Quick是Qt新引入的,Qt Quick由Qt Quick模块提供,它是一个编写QML应用的标准库。Qt Quick模块提供了两种接口:使用QML语言创建应用的QML接口和使用C++语言扩展QML的C++接口。使用Qt Quick模块,设计人员和开发人员可以轻松地构建流畅的…

【自主探索】基于 frontier_exploration 的单个机器人自主探索建图

文章目录 一、概述1、功能2、要求 二、使用方法1、用于运行演示2、用于开发人员2.1. 探索无/地图数据2.2. 使用 /map 数据进行探索 三、提供的组件1、explore_client1.1. 调用的操作1.2. 订阅主题1.3. 发布主题 2、explore_server2.1. 提供的操作2.2. 调用的操作2.3. 调用的服务…

【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷6

1、将一个空塑料袋与一个装满空气的塑料袋放到秤上称重。在两个塑料袋本身完全一样的情况下&#xff0c;得出的结果会是 A、空塑料袋更重 B、装满空气的塑料袋更重 C、两个塑料袋一样重 D、无法判断 答案&#xff1a;C 2、全球变暖带来的一个主要影响就是海平面的上升。造…

web前端开发基础----标准流布局和非标准流布局

1&#xff0c;标准流布局 标准流&#xff0c;也称文档流或普通流&#xff0c;是所有元素默认的布局方式。 在标准流中&#xff0c;元素按照其在 HTML 中出现的顺序&#xff0c;自上而下依次排列&#xff0c;并占据其父容器内的可用空间。 标准流中的元素按照其自然尺寸和位置进…

uniapp实现多时间段设置

功能说明&#xff1a; 1 点击新增时间&#xff0c;出现一个默认时间段模板&#xff0c;不能提交 2 点击“新增时间文本”&#xff0c;弹出弹窗&#xff0c;选择时间&#xff0c;不允许开始时间和结束时间同时为00:00&#xff0c; <view class"item_cont"> …

TCP/IP协议:最流行的电子邮件协议SMTP(简单邮件传输协议)详解

SMTP 是一种电子邮件协议&#xff0c;用于通过互联网从一个电子邮件帐户向另一个电子邮件帐户发送电子邮件。它是TCP/IP协议应用层的一部分。作为一种电子邮件协议&#xff0c;它建立了不同电子邮件客户端和帐户之间轻松信息交换的规则。这样&#xff0c;简单邮件传输协议就可以…

求最小的起始正整数

题目描述 给你一个整数数组 nums 。你可以选定任意的 正数 startValue 作为初始值。 你需要从左到右遍历 nums 数组&#xff0c;并将 startValue 依次累加上 nums 数组中的值。 请你在确保累加和始终大于等于 1 的前提下&#xff0c;选出一个最小的 正数 作为 startValue 。…

【Rust 日报】2023-11-23 - egui 0.24 发布

项目 - egui 0.24 发布 egui 是一个易于使用的 Rust GUI 库&#xff0c;支持在本地环境和浏览器中运行。 egui 0.24 的重要新特性是多视窗功能。在支持的后端上&#xff08;如eframe&#xff09;&#xff0c;用户可以利用全新的 viewport API 同时生成多个本机窗口。 此外&…

Git 的基本概念和使用方式。

Git 是一个开源的分布式版本控制系统&#xff0c;它可以记录代码的修改历史&#xff0c;跟踪文件的版本变化&#xff0c;并支持多人协同开发。Git 的基本概念包括&#xff1a; 1. 仓库&#xff08;Repository&#xff09;&#xff1a;存放代码和版本历史记录的地方。 2. 分支…

ArkUI开发进阶—@Builder函数@BuilderParam装饰器的妙用与场景应用

ArkUI开发进阶—@Builder函数@BuilderParam装饰器的妙用与场景应用 HarmonyOS,作为一款全场景分布式操作系统,为了推动更广泛的应用开发,采用了一种先进而灵活的编程语言——ArkTS。ArkTS是在TypeScript(TS)的基础上发展而来,为HarmonyOS提供了丰富的应用开发工具,使开…

Educational Codeforces Round 158 (Rated for Div. 2)(A~E)(贪心,树形DP)

A - Line Trip 题意&#xff1a;有一条路&#xff0c;可以用一条数线来表示。你位于数线上的点 0 &#xff0c;你想从点 0 到点 x &#xff0c;再回到点 0。你乘汽车旅行&#xff0c;每行驶 1个单位的距离要花费 1 升汽油。当您从点 0出发时&#xff0c;汽车已加满油(油箱中的…

麒麟linux离线安装dotnet core

1. 下载 dotnet core,以3.1为例 下载地址: 下载 .NET Core 3.1 (Linux、macOS 和 Windows) 查看linux cpu类型,然后根据类型下载 uname -m #结果是: aarch64 2. 放到指定目录,比如:/usr/dotnet 3. 解压dotnet-sdk-3.1.426-linux-arm64.tar.gz cd /usr/dotnet tar –zxvf a…

告别算法暗处:备案带来的光明未来

在当今数字化时代&#xff0c;算法已经成为了企业发展和创新的关键推动力。然而&#xff0c;伴随着算法的广泛应用&#xff0c;数据隐私、知识产权和法规合规等问题也引发了越来越多的关切。为了解决这些问题&#xff0c;越来越多的公司开始意识到算法备案的重要性。本文将深入…

点云从入门到精通技术详解100篇-基于深度学习的稀疏点云障碍物检测(续)

目录 3.1 连续帧点云空间特征融合 3.1.1 点云预处理 3.1.2 地面分割 3.1.3 自适应点云聚类

播放器开发(三):FFmpeg与SDL环境配置

学习课题&#xff1a;逐步构建开发播放器【QT5 FFmpeg6 SDL2】 环境配置 我这边的是使用macOS&#xff1b;IDE用的是CLion&#xff1b;CMake构建&#xff0c;除了创建项目步骤、CMakeLists文件有区别之外的代码层面不会有太大区别。 配置上只添加一下CMakeLists中FFmpeg和SD…

Ubuntu 22.04.3编译AOSP13刷机

文章目录 设备信息下载AOSP并切换分支获取设备驱动编译系统编译遇到的问题Cannot allocate memoryUbuntu设置USB调试刷机参考链接 设备信息 手机&#xff1a;Pixel 4XL 下载AOSP并切换分支 在清华大学开源软件镜像站下载初始化包aosp-latest.tar。 解压缩&#xff0c;切换到…

解决LocalDateTime传输前端为时间的数组

问题出现如下&#xff1a; 问题出现原因&#xff1a; 默认序列化情况下会使用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS。使用这个解析时就会打印出数组。 解决方法&#xff1a; 我在全文搜索处理方法总结如下&#xff1a; 1.前端自定义函数来书写 ,cols: [[ //表头{…

[ubuntu]ubuntu上如何彻底卸载C++的opencv而不影响下次安装使用

问题场景&#xff1a;我在ubuntu上安装编译了opencv3.4.4之后我又想安装opencv4.5.0结果装上后&#xff0c;opencv库在系统目录很混乱导致出现cmake项目出现很多错误。因此又想卸载掉opencv3.4.4重新安装opencv4.5.0进去。但是如何卸载呢&#xff1f;我们知道opencv在系统里面有…

Go事件管理器:简单实现

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等&#xff0c;您的关注将是我的更新动力&#xff01; 在编程中&#xff0c;事件管理器是一种常见的工具&#xff0c;用于通过通知来触发操作。在Go语言中&#xff0c;我们可以通过创建…