【Maven技术专题】「入门到精通」教你如何使用Maven中引用依赖本地Jar包,并进行打包输出

前言

在使用Maven管理Java项目时,有时需要引入一些存放在系统特定位置的JAR文件。这些JAR文件可能是你自己编写的,也可能是其他来源的。无论是哪种情况,使用 Maven 的 system 范围和 systemPath 参数,可以方便地引入这些本地依赖。

仓库分类

在Java开发中,Maven是非常重要的构建工具,他的仓库机制用于存储和管理项目的依赖。Maven仓库大致可以分为两类:本地仓库和远程仓库。
在这里插入图片描述

本地仓库

本地仓库是开发者本地机器上的仓库,所有下载的或者由Maven构建生成的项目的构件(artifact)都存储在这里。这种仓库只能被你的Maven客户端访问

本地仓库的位置

Maven本地仓库默认情况下位于当前用户的主目录下的.m2目录,即“C:\Users{用户名}.m2\repository”这个位置,这个本地仓库用于存储Maven下载的所有依赖库文件。

修改对应的本地仓库位置

通过更改Maven的全局设置文件settings.xml来改变本地仓库的位置。这个文件位于你Maven安装目录的conf目录下。在settings.xml文件中,你可以找到localRepository这个标签,该标签默认会被注释掉,移除注释并设置新的路径就可以改变本地仓库的位置。

在开发过程中,如果你有一个Java项目或模块(比如一个构建了的jar文件),想把它作为一个本地的依赖供其他项目或模块使用,你可以通过Maven的Install插件来做到这一点。Install插件负责将项目构件安装到本地仓库,《mvn clean install》这条命令将会清除目标目录下的旧版本构建文件,然后生成新的构建文件,并将其安装到本地仓库。这样,其他依赖此构件的模块便能从本地仓库中获取到这个依赖,从而进行进一步的构建和开发。

远程仓库

远程仓库是部署在web服务器上的,可以被多个构建项目共享。

远程仓库的种类

远程仓库主要包括下列三种:
在这里插入图片描述

  • 中央仓库:Maven 中央仓库是一个由Maven社区维护的,项目中通常都会用到的开源构建会被发布到此处。Maven 会默认从该仓库获取依赖包,不需要进行额外配置。

  • 私服仓库:如果发现从中央仓库下载构建过慢,或者需要存储公司内部的专有构建,可以配置私有仓库(如Nexus或Artifactory)。

  • 其他仓库:除了Maven中央仓库以外还有其他第三方维护的公共库,这些库里面可能会包含中央仓库中没有的一些依赖包。

依赖搜索顺序

Maven的搜索顺序是先本地仓库,然后再远程仓库,而远程仓库中,先搜索私服,其次才是中央仓库和其他公共库,这样的安排既保证了优先使用本地资源,节省了宽带,也能保证依赖库的及时更新。
在这里插入图片描述

使用system scope+systemPath

Maven使用system范围与systemPath参数来引用本地的JAR文件。

system scope的作用

当使用 system scope 指定依赖时,Maven会在系统中查找已经存在的该依赖,如果存在则直接使用,避免再次去远程仓库中查找。然而,如果该依赖在系统中不存在,后续操作依然会失败。因此,在使用 system 范围引入依赖之前,确保该依赖在你的系统中存在。这是一个需要注意的问题。

systemPath的作用

systemPath 参数用于指定依赖在系统中的绝对路径,这样 Maven 在编译时就可以直接使用这个路径来查找依赖。如果同一个依赖在工程中多次使用,重复指定 systemPath 参数比较繁琐。为了避免这种情况,可以考虑使用 Maven 的 project.parent 或 dependencyManagement 来进行统一管理。这样可以将依赖的版本、scope 等信息放在一个地方进行管理,使得项目结构更加清晰和易于维护。在实际项目中,这种方式往往会提高开发效率,减少错误的发生。

使用案例

Maven项目中的一个 dependencies 配置,用于指定项目需要依赖的外部 jar 包。具体来说,这个配置中指定了一个 groupId 为 com.liboware,artifactId 为 my-jar,version 为 1.0 的外部 jar 包,并且给这个依赖设置了系统作用域(scope),同时指定了这个 jar 包在本地文件系统中的路径。

依赖的引入

  <dependencies>
    <dependency>
      <groupId>com.liboware</groupId>
      <artifactId>my-jar</artifactId>
      <version>1.0</version>
      <scope>system</scope>
      <systemPath>${project.basedir}/lib/my-jar.jar</systemPath>
    </dependency>
  </dependencies>

scope属性的取值分别有 compile、provided、runtime、test 和 system,分别表示依赖在编译、运行、测试中的作用域,而 system 则表示不需要从 Maven 仓库中下载,而是直接使用本地系统中 jar 包的路径,适用于一些本地 jar 包的使用场景。在本例中,使用了 system 作用域,并指定了本地 jar 包的路径为 ${project.basedir}/lib/my-jar.jar

所引发的隐患问题

这种配置方式比较灵活,适用于一些需要使用本地 jar 包的场景,但同时也存在一些问题。由于使用 system 作用域时,Maven 不再管理依赖 jar 包的版本信息,这可能会导致不同版本的 jar 包之间冲突的问题,因此需要额外的注意依赖 jar 包的版本号和文件路径的正确性。

打包处理插件

当使用 Maven 的打包插件 jar-with-dependencies 打包时,使用system作用域引入的依赖包将不会被包含在输出的可执行 jar 文件中。如果需要将本地依赖包打入可执行 jar 文件中,可以通过 Maven 的resources标签进行配置。

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
              <finalName>xxx-jar-with-dependencies</finalName>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
     <resources>
      <resource>
        <targetPath>lib/</targetPath>
        <directory>lib/</directory>
        <includes>
          <include>**/*.jar</include>
        </includes>
      </resource>
    </resources>
  </build>

这段 Maven 配置主要实现了使用 maven-shade-plugin 插件打包项目,并将依赖的第三方库和应用程序代码打包在一个可执行的 jar 文件中。同时,还将本地依赖包 *.jar 打包进可执行 jar 文件中。

具体来说,该配置包含以下内容:

  • maven-shade-plugin 插件配置:该插件用于打包和重写 jar 文件
    • descriptorRefs:指定打包类型,这里配置为 jar-with-dependencies,表示打出包含依赖的 jar 包
    • finalName:指定可执行 jar 包的文件名
  • resources 配置:将本地依赖包打包进 jar 文件中
    • targetPath:指定本地依赖包在 jar 中的存储路径
    • directory:指定本地依赖包的存储路径
    • includes:指定需要打包进 jar 文件中的本地依赖包

总的来说,这个配置文件展示了一个简单的 Maven 打包过程的流程,通过 maven-shade-plugin 插件实现了将项目及其依赖(包括本地依赖包)打包在一个 jar 文件中的需求。

打包结果以及效果

生成的 xxx-jar-with-dependencies.jar 将会包含 lib 目录以及其中的 *.jar 文件,该 jar 包在执行时可以找到这些依赖包。

但有时这种方法可能会失效,比如在声明 JDBCDriver 时,使用 Class.forName("xxx.Driver") 时可能会报类找不到的错误。此时可以使用以下两种方法来解决:

  • 将依赖的 JDBC 驱动包作为单独的依赖项,在运行时通过 -cp 参数指定类路径,例如:java -cp xxx-jar-with-dependencies.jar:mysql-connector-java-8.0.25.jar com.example.Main
  • 将依赖的 JDBC 驱动包打包进 xxx-jar-with-dependencies.jar,并在运行时手动调用 ClassLoader 加载该依赖包中的类。

使用mvn install:install-file

可以使用以下命令将 .jar 包安装到本地 Maven 仓库中:

mvn install:install-file -Dfile=my-jar.jar -DgroupId=com.liboware -DartifactId=my-jar -Dversion=1.0 -Dpackaging=jar

其中:

  • -Dfile:指定要安装的 .jar 文件的位置和文件名。
  • -DgroupId:指定 Maven 项目的 GroupId。
  • -DartifactId:指定 Maven 项目的 ArtifactId。
  • -Dversion:指定 Maven 项目的版本号。
  • -Dpackaging:指定 Maven 项目的打包方式(例如:jar、war、pom 等)。

添加 in project repository

如果你希望在一个新机器上执行 Maven 项目时不用运行 mvn install:install-file 命令,你可以将你的 .jar 包添加到项目的本地仓库中。

在项目的 pom.xml 文件中,可以声明一个 <repositories> 元素来定义项目的本地仓库。例如:

<repositories>
    <repository>
        <id>my-local-repository</id>
        <url>file://${project.basedir}/lib</url>
    </repository>
</repositories>

在上面的示例中,我们定义了一个 my-local-repository 的仓库,它的 URL 是 ${project.basedir}/lib,也就是项目的 lib 文件夹。

现在,你可以将你的 .jar 包放到项目的 lib 文件夹下,当你执行 Maven 命令时,Maven 就会从这个 my-local-repository 仓库中查找你的 .jar 包了。

<dependency>
    <groupId>com.liboware</groupId>
    <artifactId>my-jar</artifactId>
    <version>1.0</version>
</dependency>

你的jar包及路径必须严格遵循格式:

/groupId/artifactId/version/artifactId-verion.jar

本例中:lib/com/liboware/my-jar/1.0/my-jar-1.0.jar

内容总结

Maven中,可用system范围和systemPath参数引用本地.jar文件,或使用mvn install:install-file命令安装到本地仓库。为了省去在新机器上安装的麻烦,需在pom.xml文件中声明<repositories>元素指定本地仓库路径,以便Maven自动查找依赖。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023-12-05 Qt学习总结10

点击 <C 语言编程核心突破> 快速C语言入门 Qt学习总结 前言二十六 学生信息管理系统插入介绍: QTableView和QSqlTableModelQTableViewQSqlTableModel 程序所用数据库表格程序组成以及界面学生端源码:管理员端源码: 总结 前言 要解决问题: 学习qt最核心知识, 多一个都不…

【MySQL】:数据类型

数据类型 一.数值类型1.整数1.tinyint2.bit类型 2.浮点类型1.float2.decimal 二.字符串类型1.char类型2.varchar类型3.char和varchar的区别4.日期和时间类型5.enum和set 三.集合查询 一.数值类型 1.整数 1.tinyint 正常插入 越界插入 如果我们向mysql特定的类型中插入不合法的…

[WMCTF2020]Make PHP Great Again require_once 特性

php源码分析 require_once 绕过不能重复包含文件的限制-安全客 - 安全资讯平台 这里是特性 我们首先来解释一下 <?php highlight_file(__FILE__); require_once flag.php; if(isset($_GET[file])) {require_once $_GET[file]; }这个是我们的源代码 PHP包含的格式是将 已…

SpringBoot系列之基于Jedis实现分布式锁

Redis系列之基于Jedis实现分布式锁 1、为什么需要分布式锁 在单机环境&#xff0c;我们使用最多的是juc包里的单机锁&#xff0c;但是随着微服务分布式项目的普及&#xff0c;juc里的锁是不能控制分布锁环境的线程安全的&#xff0c;因为单机锁只能控制同个进程里的线程安全&…

12月12日作业

设计一个闹钟 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> #include <QTime> #include <QTime> #include <QTextToSpeech>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass …

开发提测?

前言 开发提测是正式开始测试的重要关卡&#xff0c;提测质量的好坏会直接影响测试阶段的效率&#xff0c;进而影响项目进度。较好的提测质量&#xff0c;对提高测试效率和优化项目进度有着事半功倍的作用。如何更好的推进开发提高提测质量呢&#xff1f;下面小编结合自己项目…

优化算法 学习记录

文章目录 相关资料 优化算法梯度下降学习率牛顿法 随机梯度下降小批量随机梯度下降动量法动量法解决上述问题 AdaGrad 算法RMSProp算法Adam学习率调度器余弦学习率调度预热 相关资料 李沐 动手学深度学习 优化算法 优化算法使我们能够继续更新模型参数&#xff0c;并使损失函…

【数据安全】金融行业数据安全保障措施汇总

数字化的今天&#xff0c;数据的价值不可估量&#xff0c;尤其是金融行业&#xff0c;数据不仅代表着企业的核心资产&#xff0c;还涉及到客户的隐私和信任。因此对于金融行业而言&#xff0c;保障数据安全至关重要。下面我们就来一起讨论为什么金融行业要保障数据安全&#xf…

基于Qt的蓝牙Bluetooth在ubuntu实现模拟

​# 前言 Qt 官方提供了蓝牙的相关类和 API 函数,也提供了相关的例程给我们参考。笔者根据 Qt官方的例程编写出适合我们 Ubuntu 和 gec6818开发板的例程。注意 Windows 上不能使用 Qt 的蓝牙例程,因为底层需要有 BlueZ协议栈,而 Windows 没有。Windows 可能需要去移植。笔者…

代码随想录算法训练营第三十六天|01背包问题 二维 ,01背包问题 一维 ,416. 分割等和子集

背包理论基础 01 背包&#xff08;二维&#xff09; 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 背包最大重量为4。 物品为&#x…

Docker入门指南:从基础到实践

在当今软件开发领域&#xff0c;Docker已经成为一种不可或缺的工具。通过将应用程序及其依赖项打包成轻量级的容器&#xff0c;Docker实现了开发、测试和部署的高度一致性。本文将深入研究Docker的基本概念&#xff0c;并通过详细的示例代码演示如何应用这些概念于实际场景中。…

学习IO的第八天

作业&#xff1a;使用信号灯循环输出ABC sem.c #include <head.h>union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminf…

InnoDB在SQL查询中的关键功能和优化策略

文章目录 前言存储引擎介绍存储引擎是干嘛的InnoDB的体系结构 InnoDB的查询操作InnoDB的查询原理引入 Buffer Pool引入数据页Buffer Pool 的结构数据页的加载Buffer Pool 的管理Buffer Pool 的优化 总结 前言 通过上篇文章《MySQL的体系结构与SQL的执行流程》了解了SQL语句的执…

IO第二天作业

1.用read write函数实现文件拷贝 程序 #include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h> #include <stdlib.h> #include <string.h>int main(int argc, const char *argv[]){…

孩子还是有一颗网安梦——Bandit通关教程:Level 9 → Level 10

&#x1f575;️‍♂️ 专栏《解密游戏-Bandit》 &#x1f310; 游戏官网&#xff1a; Bandit游戏 &#x1f3ae; 游戏简介&#xff1a; Bandit游戏专为网络安全初学者设计&#xff0c;通过一系列级别挑战玩家&#xff0c;从Level0开始&#xff0c;逐步学习基础命令行和安全概念…

初学编程100个代码,python 基础 详细

本篇文章给大家谈谈初学编程100个代码&#xff0c;以及python 基础 详细&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 1.Python标识符 在 Python 里&#xff0c;标识符有字母、数字、下划线组成。 在 Python 中&#xff0c;所有标识符可以包括英文、数字以…

新版Spring Security6.2架构 (二) - Authentication

前言&#xff1a; 书接上文&#xff0c;继续官网的个人翻译和个人理解&#xff0c;有不对的请见谅。第一个篇博客中写到Sevlet appliation的总体架构&#xff0c;本博客是写Sevlet appliation中Authentication的架构&#xff0c;在后面第三篇博客将会写到新版spring security如…

IO流(一)

目录 一.关于IO流 二.字节流 1.FIleOutputStream&#xff08;字节输出流&#xff09; 1.书写步骤&#xff1a; 1.创建字节输出流对象 2.写数据 3.释放资源 2.书写数据的三种方式 3.换行写入数据&#xff1a; 4.续写 2.FileInputStream&#xff08;字节输入流&#xf…

【算法-字符串3】听说KMP很难?进来看这篇:实现strstr(),查找子串

今天&#xff0c;带来KMP算法的讲解。文中不足错漏之处望请斧正&#xff01; 理论基础点这里 今天我们来实现strstr()。 题意转化 在一个字符串mainStr中找另一个字符串subStr。 解决思路 两指针i和j分别在mainStr和subStr中拿取字符尝试匹配 匹配&#xff1a;继续不匹配&…

HTML实现页面

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>工商银行电子汇款单</title> </head> &…