前言

在使用 Maven 构建 Java 项目时,我们常常需要对项目的打包过程进行精细化控制,尤其是希望排除某些特定的依赖库。这可能是为了减小最终构建产物的体积、避免版本冲突,或者仅仅是为了满足不同环境下的部署需求。

本文将详细介绍如何在 Maven 打包过程中排除特定依赖,涵盖多种常见插件和配置方式,帮助你灵活控制项目的打包内容。


一、理解 Maven 的依赖作用域(Scope)

在深入讨论排除依赖之前,先了解 Maven 中的依赖作用域是非常重要的。不同的作用域决定了依赖是否会被包含在构建输出中:

Scope描述
compile默认作用域,适用于所有阶段(编译、测试、运行)
provided编译和测试阶段可用,但不会被打包进最终输出(如 Servlet API)
runtime运行和测试阶段需要,但编译不需要(如 JDBC 驱动)
test仅用于测试阶段,不会被打包
system类似于 provided,但必须显式指定本地路径
import仅用于 <dependencyManagement> 中导入其他 POM 的依赖

最佳实践建议:优先使用合适的 scope 来控制依赖是否被打包,而不是通过插件强行剔除。


二、使用 Maven Shade Plugin 排除依赖

如果你使用的是 maven-shade-plugin 来构建一个包含所有依赖的 fat jar(即 uber jar),可以通过 <excludes> 标签来排除特定依赖。

示例配置:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.5.0</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><excludes><exclude>com.example:unwanted-library</exclude><exclude>org.slf4j:slf4j-simple</exclude></excludes><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><mainClass>com.example.Main</mainClass></transformer></transformers></configuration></execution></executions>
</plugin>

说明

  • <exclude> 的格式为 groupId:artifactId,可以精确到版本号。
  • 适合用于构建包含多个模块和依赖的单体 JAR 包。

三、使用 Maven Assembly Plugin 排除依赖

如果你使用 maven-assembly-plugin 来打包一个包含依赖的 zip/jar 包,也可以通过 <excludes> 来排除某些依赖。

示例配置:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.6.0</version><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifest><mainClass>com.example.Main</mainClass></manifest></archive><excludes><exclude>com.example:unwanted-library</exclude><exclude>org.slf4j:slf4j-api</exclude></excludes></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions>
</plugin>

提示:Assembly 插件还支持自定义 assembly.xml 文件,实现更细粒度的控制。


四、使用 Maven Jar Plugin 排除资源或类文件

默认的 maven-jar-plugin 不会把依赖打进 JAR 包中,但如果你有特殊需求(如手动管理 lib 目录),可以用来排除某些资源或类文件。

示例配置(排除资源):

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.7.0</version><configuration><excludes><exclude>**/unwanted/**</exclude></excludes></configuration>
</plugin>

五、使用 Maven Dependency Plugin 清理依赖

如果你想在打包前主动清理某些依赖,可以使用 maven-dependency-plugin 来复制依赖并排除部分库。

示例配置:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>3.6.0</version><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/lib</outputDirectory><overWriteReleases>false</overWriteReleases><overWriteSnapshots>false</overWriteSnapshots><overWriteIfNewer>true</overWriteIfNewer><excludes><exclude>com.example:unwanted-library</exclude></excludes></configuration></execution></executions>
</plugin>

此方法适合手动构建 lib 目录,并配合 shell 脚本或 Dockerfile 使用。


六、Docker 构建中排除依赖(Maven + Docker)

如果你使用 Maven 构建镜像(如结合 Jib、Dockerfile 等),可以在构建应用 JAR 包时就排除依赖,再将其 COPY 到 Docker 镜像中。

示例(结合 jib-maven-plugin):

<plugin><groupId>com.google.cloud.tools</groupId><artifactId>jib-maven-plugin</artifactId><version>3.3.2</version><configuration><container><entrypoint><arg>java</arg><arg>-cp</arg><arg>/app/resources:/app/classes:/app/libs/*</arg><arg>com.example.Main</arg></entrypoint></container><extraDirectories><paths><path><from>src/main/resources</from><into>/app/resources</into></path></paths></extraDirectories></configuration>
</plugin>

在此示例中,你可以先通过其他方式控制哪些依赖被放入 /app/libs/


七、使用 <scope> 显式排除依赖

最简单且推荐的方式是直接在 pom.xml 中设置依赖的作用域为 testprovided,这样它们就不会被打包进最终输出。

示例:

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope>
</dependency>

Maven 会根据作用域自动决定是否将该依赖包含在构建输出中。


八、使用 <optional> 标记依赖为可选

如果你开发的是一个库(library),并且某个依赖不是必需的,可以将其标记为 <optional>true</optional>,这样引入你的库的项目可以选择是否包含这个依赖。

示例:

<dependency><groupId>com.example</groupId><artifactId>some-utils</artifactId><version>1.0.0</version><optional>true</optional>
</dependency>

注意:<optional> 不会影响当前项目的打包行为,而是影响下游项目的依赖管理。


九、使用 <exclusion> 排除传递性依赖

有时你想排除某个依赖的子依赖(transitive dependency),可以使用 <exclusions>

示例:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion><exclusion><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId></exclusion></exclusions>
</dependency>

这种方式非常适合解决依赖冲突或精简依赖树。


十、综合建议与最佳实践

场景推荐做法
测试依赖不打包设置 <scope>test</scope>
容器已提供依赖(如 Tomcat、JDK)设置 <scope>provided</scope>
某些依赖不想被打入最终 JAR/WAR使用 Shade / Assembly 插件配置 <excludes>
排除某个依赖的子依赖使用 <exclusions> 标签
控制依赖是否传递给下游项目使用 <optional>true</optional>
构建 lib 目录时排除某些库使用 maven-dependency-plugin<excludes>
构建 Docker 镜像时排除依赖结合上述方法先处理好 JAR 再 COPY

总结

Maven 提供了多种灵活的方式来排除特定依赖,从简单的 <scope> 到复杂的插件配置,开发者可以根据实际需求选择最合适的方法。合理使用这些技巧不仅可以减小最终包的体积,还能有效避免依赖冲突问题,提高构建效率和部署稳定性。


常见问答

Q:我只想排除某个依赖的一个 jar 文件?

A:可以使用 <exclusion> 排除其子依赖,或者使用插件配置 <excludes>

Q:为什么设置了 <scope>provided</scope> 依赖仍然被打包?

A:检查是否被其他插件强制引入,例如 maven-shade-plugin

Q:我想在 Spring Boot 项目中排除某些 starter 自带的依赖怎么办?

A:使用 <exclusions> 标签,在对应的 starter 依赖中声明要排除的子依赖。

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

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

相关文章

Terraform `for_each` 精讲:优雅地自动化多域名证书验证

大家好&#xff0c;在云原生和自动化运维的世界里&#xff0c;Terraform无疑是基础设施即代码&#xff08;IaC&#xff09;领域的王者。它强大的声明式语法让我们能够轻松地描述和管理云资源。然而&#xff0c;即使是经验丰富的工程师&#xff0c;在面对某些动态场景时也可能会…

C++标准库中各种互斥锁的用法 mutex

示例 仅供参考学习 #include <mutex> #include <shared_mutex> #include <thread> #include <chrono> #include <iostream> #include <vector>// // 1. std::mutex - 基本互斥锁 // void basic_mutex_example() {std::mutex mtx;int cou…

Android Handler机制与底层原理详解

Android 的 Handler 机制是跨线程通信和异步消息处理的核心框架&#xff0c;它构成了 Android 应用响应性和事件驱动模型的基础&#xff08;如 UI 更新、后台任务协调&#xff09;。其核心思想是 “消息队列 循环处理”。 核心组件及其关系Handler (处理器): 角色: 消息的发送…

jQuery JSONP:实现跨域数据交互的利器

jQuery JSONP&#xff1a;实现跨域数据交互的利器 引言 随着互联网的发展&#xff0c;跨域数据交互的需求日益增加。在Web开发中&#xff0c;由于同源策略的限制&#xff0c;直接通过XMLHttpRequest请求跨域数据会遇到诸多问题。而JSONP&#xff08;JSON with Padding&#xff…

Redis集群和 zookeeper 实现分布式锁的优势和劣势

在分布式系统中&#xff0c;实现分布式锁是确保多个节点间互斥访问共享资源的一种常见需求。Redis 集群 和 zookeeper 都可以用来实现这一功能&#xff0c;但它们有着各自不同的优势和劣势。 CAP 理论&#xff1a; 在设计一个分布式系统时&#xff0c;一致性&#xff08;Consis…

如何备份vivo手机中的联系人?

随着vivo移动设备在全球设立7个研发中心&#xff0c;vivo正在进入更多的国家。如今&#xff0c;越来越多的人开始使用vivo手机。以vivo X100为例&#xff0c;它配备了主摄像头和多个辅助摄像头&#xff0c;提供多样化的拍摄选项&#xff0c;并搭载了最新的FunTouch OS&#xff…

python脚本编程:使用BeautifulSoup爬虫库获取热门单机游戏排行榜

BeautifulSoup是一个便捷的解析html页面元素的python库&#xff0c;此处用来写一个简单的爬虫批量抓取国内游戏资讯网站的近期热门单机游戏排行榜。 网页来源如下所示代码 from bs4 import BeautifulSoup import requests# get web page web_url "https://www.3dmgame.co…

C#配置全面详解:从传统方式到现代配置系统

C#配置全面详解&#xff1a;从传统方式到现代配置系统 在软件开发中&#xff0c;配置是指应用程序运行时可调整的参数集合&#xff0c;如数据库连接字符串、API 地址、日志级别等。将这些参数从代码中分离出来&#xff0c;便于在不修改代码的情况下调整应用行为。C# 提供了多种…

数据中台架构解析:湖仓一体的实战设计

目录 一、数据中台与湖仓一体架构是什么 1. 数据中台 2. 湖仓一体架构 3. 湖仓一体在数据中台里的价值 二、湖仓一体架构的核心部件 1. 数据湖 2. 数据仓库 3. 数据集成工具 4. 数据分析与处理引擎 三、湖仓一体架构实战设计 1. 需求分析与规划 2. 数据湖建设 3. …

SQL Server表分区技术详解

表分区概述 表分区是将大型数据库表物理分割为多个较小单元的技术,逻辑上仍表现为单一实体。该技术通过水平分割数据显著提升查询性能,尤其针对TB级数据表可降低90%的响应时间。典型应用场景包含订单历史表、日志记录表等具有明显时间特征的业务数据,以及需要定期归档的审计…

WHIP(WebRTC HTTP Ingestion Protocol)详解

WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;详解 WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;是一种基于 HTTP 的协议&#xff0c;用于将 WebRTC 媒体流推送到媒体服务器&#xff08;如 SRS、Janus、LiveKit&#xff09;。它是为简化 WebRT…

图像噪点消除:用 OpenCV 实现多种滤波方法

在图像处理中&#xff0c;噪点是一个常见的问题。它可能是由于图像采集设备的缺陷、传输过程中的干扰&#xff0c;或者是光照条件不佳引起的。噪点会影响图像的质量和后续处理的效果&#xff0c;因此消除噪点是图像预处理的重要步骤之一。本文将介绍如何使用 OpenCV 实现几种常…

AI的Prompt提示词:英文写好还是中文好?

在与AI人大模型交互时,Prompt(提示词)的质量直接决定了输出的精准度和有效性。一个常见的问题是:究竟是用英文写Prompt好,还是用中文写更好?这并非一个简单的二元选择,而是涉及到语言模型的底层逻辑、表达的精确性以及个人使用习惯的综合考量。 英文Prompt的优势 模型训…

react的条件渲染【简约风5min】

const flag1true; console.log(flag1&&hello); console.log(flag1||hello); const flag20; console.log(flag2&&hello); console.log(flag2||hello); // &&运算符&#xff0c;如果第一个条件为假&#xff0c;则返回第一个条件&#xff0c;否则返回第二…

【RK3568+PG2L50H开发板实验例程】FPGA部分 | 紫光同创 IP core 的使用及添加

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com)1.实验简介实验目的&#xff1a;了解 PDS 软件如何安装 IP、使用 IP 以及查看 IP 手册实验环境&#xff1a;Window11 PD…

thinkphp微信小程序一键获取手机号登陆(解密数据)

微信小程序获取手机号登录的步骤相对较为简单,主要分为几个部分: 1.用户授权获取手机号: 微信小程序通过调用 wx.getPhoneNumber API 获取用户授权后,获取手机号。 2.前端获取用户的手机号: 用户在小程序中点击获取手机号时,系统会弹出授权框,用户同意后,你可以通过 …

数据库设计精要:完整性和范式理论

文章目录数据的完整性实体的完整性主键域完整性参照完整性外键多表设计/多表理论一对一和一对多多对多数据库的设计范式第一范式&#xff1a;原子性第二范式&#xff1a;唯一性第三范式&#xff1a;不冗余性数据的完整性 实体的完整性 加主键&#xff0c;保证一个表中每一条数…

智能推荐社交分享小程序(websocket即时通讯、协同过滤算法、时间衰减因子模型、热度得分算法)

&#x1f388;系统亮点&#xff1a;websocket即时通讯、协同过滤算法、时间衰减因子模型、热度得分算法&#xff1b;一.系统开发工具与环境搭建1.系统设计开发工具后端使用Java编程语言的Spring boot框架项目架构&#xff1a;B/S架构运行环境&#xff1a;win10/win11、jdk17小程…

部署NextCloud AIO + Frp + nginx-proxy-manager内网穿透私有云服务

网络拓扑 假设已有域名为nextcloud.yourhost.com 用户通过域名https访问 -> Nginx -> frps -> frpc -> NextCloud 其中Nginx和frps安装在具有公网IP的服务器上&#xff0c;frpc和NextCloud安装在内网服务器中。 Nginx配置 通过docker安装nginx-proxy-manager 外…

【源力觉醒 创作者计划】文心开源大模型ERNIE-4.5-0.3B-Paddle私有化部署保姆级教程及技术架构探索

一起来轻松玩转文心大模型吧&#x1f449;一文心大模型免费下载地址: https://ai.gitcode.com/theme/1939325484087291906 前言 2025年6月30日&#xff0c;百度正式开源文心大模型4.5系列&#xff08;ERNIE 4.5&#xff09;&#xff0c;涵盖10款不同参数规模的模型&#xff0…