Maven&Nexus

Maven&Nexus

  • [4. Maven的使用](#4. Maven的使用)
    • [4.1 下载Maven](#4.1 下载Maven)
    • [4.2 配置Maven](#4.2 配置Maven)
      • [4.2.1 配置环境变量](#4.2.1 配置环境变量)
      • [4.2.2 配置Maven工具参数](#4.2.2 配置Maven工具参数)
        • [4.2.2.1 配置本地仓库](#4.2.2.1 配置本地仓库)
        • [4.2.2.2 配置远程仓库](#4.2.2.2 配置远程仓库)
        • [4.2.2.3 JDK21自适应构建配置](#4.2.2.3 JDK21自适应构建配置)
      • [4.2.3 IDEA集成Maven](#4.2.3 IDEA集成Maven)
        • [4.2.3.1 创建一个空的工程(建议)](#4.2.3.1 创建一个空的工程(建议))
        • [4.2.3.2 设置空工程的JDK(建议)](#4.2.3.2 设置空工程的JDK(建议))
        • [4.2.3.3 集成Maven](#4.2.3.3 集成Maven)
    • [4.3 手动开发Maven项目](#4.3 手动开发Maven项目)
    • [4.4 IDEA开发Maven Java项目](#4.4 IDEA开发Maven Java项目)
      • [4.4.1 创建Maven模块](#4.4.1 创建Maven模块)
      • [4.4.2 补齐目录(非必须)](#4.4.2 补齐目录(非必须))
      • [4.4.3 添加junit5依赖](#4.4.3 添加junit5依赖)
      • [4.4.4 编写Java程序](#4.4.4 编写Java程序)
      • [4.4.5 编写测试程序](#4.4.5 编写测试程序)
    • [4.5 IDEA开发Maven JavaWeb项目](#4.5 IDEA开发Maven JavaWeb项目)
      • [4.5.1 第一种方式:全部手动配置](#4.5.1 第一种方式:全部手动配置)
        • [4.5.1.1 创建Java Maven模块](#4.5.1.1 创建Java Maven模块)
        • [4.5.1.2 手动创建目录](#4.5.1.2 手动创建目录)
        • [4.5.1.3 提供web.xml配置](#4.5.1.3 提供web.xml配置)
        • [4.5.1.4 添加打包方式和依赖](#4.5.1.4 添加打包方式和依赖)
      • [4.5.2 第二种方式:在Module上添加Web支持](#4.5.2 第二种方式:在Module上添加Web支持)
        • [4.5.2.1 创建Java Maven模块](#4.5.2.1 创建Java Maven模块)
        • [4.5.2.2 打开项目结构](#4.5.2.2 打开项目结构)
        • [4.5.2.3 在Module上添加Web支持](#4.5.2.3 在Module上添加Web支持)
        • [4.5.2.4 打包方式war并添加servlet依赖](#4.5.2.4 打包方式war并添加servlet依赖)
      • [4.5.3 第三种方式:通过Maven的webapp原型创建](#4.5.3 第三种方式:通过Maven的webapp原型创建)
        • [4.5.3.1 选择Archetype](#4.5.3.1 选择Archetype)
        • [4.5.3.2 修改web.xml(可选)](#4.5.3.2 修改web.xml(可选))
        • [4.5.3.3 添加servlet依赖](#4.5.3.3 添加servlet依赖)
      • [4.5.4 编写Servlet并部署项目到Tomcat](#4.5.4 编写Servlet并部署项目到Tomcat)
    • [4.6 快速拷贝Maven项目](#4.6 快速拷贝Maven项目)
  • [5. Maven的依赖管理](#5. Maven的依赖管理)
    • [5.1 什么是依赖范围](#5.1 什么是依赖范围)
      • [5.1.1 compile](#5.1.1 compile)
      • [5.1.2 test](#5.1.2 test)
      • [5.1.3 provided](#5.1.3 provided)
      • [5.1.4 runtime](#5.1.4 runtime)
      • [5.1.5 system](#5.1.5 system)
      • [5.1.6 import](#5.1.6 import)
    • [5.2 什么是依赖传递](#5.2 什么是依赖传递)
    • [5.3 依赖范围对依赖传递的影响](#5.3 依赖范围对依赖传递的影响)
      • [5.3.1 主要依赖范围及其传递影响](#5.3.1 主要依赖范围及其传递影响)
      • [5.3.2 编写程序测试](#5.3.2 编写程序测试)
    • [5.4 Maven是如何解决依赖冲突的](#5.4 Maven是如何解决依赖冲突的)
      • [5.4.1 什么是依赖冲突](#5.4.1 什么是依赖冲突)
      • [5.4.2 依赖冲突的解决方案](#5.4.2 依赖冲突的解决方案)
        • [5.4.2.1 版本锁定](#5.4.2.1 版本锁定)
        • [5.4.2.2 短路径优先(就近原则)](#5.4.2.2 短路径优先(就近原则))
        • [5.4.2.3 声明优先](#5.4.2.3 声明优先)
        • [5.4.2.4 特殊优先(后来者居上)](#5.4.2.4 特殊优先(后来者居上))
        • [5.4.2.5 可选依赖](#5.4.2.5 可选依赖)
        • [5.4.2.6 排除依赖](#5.4.2.6 排除依赖)
    • [5.5 刷新依赖的几种方式](#5.5 刷新依赖的几种方式)
    • [5.6 资源文件的指定](#5.6 资源文件的指定)
  • [6. Maven的继承和聚合](#6. Maven的继承和聚合)
    • [6.1 什么是Maven的继承](#6.1 什么是Maven的继承)
    • [6.2 packaging必须是pom](#6.2 packaging必须是pom)
    • [6.3 子工程继承父工程的什么](#6.3 子工程继承父工程的什么)
    • [6.4 父工程示例](#6.4 父工程示例)
    • [6.5 子工程示例](#6.5 子工程示例)
    • [6.6 什么是Maven的聚合](#6.6 什么是Maven的聚合)
    • [6.7 聚合项目的作用](#6.7 聚合项目的作用)
  • [7. Maven私服](#7. Maven私服)
    • [7.1 什么是私服](#7.1 什么是私服)
    • [7.2 Maven仓库管理器Nexus](#7.2 Maven仓库管理器Nexus)
      • [7.2.1 什么是Nexus](#7.2.1 什么是Nexus)
      • [7.2.2 Nexus仓库的类型](#7.2.2 Nexus仓库的类型)
      • [7.2.3 仓库为什么要分类](#7.2.3 仓库为什么要分类)
      • [7.2.4 安装Nexus](#7.2.4 安装Nexus)
        • [7.2.4.1 下载Nexus](#7.2.4.1 下载Nexus)
        • [7.2.4.2 解压安装Nexus](#7.2.4.2 解压安装Nexus)
        • [7.2.4.3 启动Nexus服务](#7.2.4.3 启动Nexus服务)
        • [7.2.4.4 访问Nexus](#7.2.4.4 访问Nexus)
    • [7.3 Nexus私服的应用](#7.3 Nexus私服的应用)
      • [7.3.1 浏览仓库](#7.3.1 浏览仓库)
      • [7.3.2 设置仓库](#7.3.2 设置仓库)
        • [7.3.2.1 创建仓库](#7.3.2.1 创建仓库)
        • [7.3.2.2 创建代理仓库](#7.3.2.2 创建代理仓库)
        • [7.3.2.3 创建宿主仓库:Release](#7.3.2.3 创建宿主仓库:Release)
        • [7.3.2.4 创建宿主仓库:Snapshot](#7.3.2.4 创建宿主仓库:Snapshot)
        • [7.3.2.5 创建仓库组](#7.3.2.5 创建仓库组)
      • [7.3.3 使用Nexus下载jar包](#7.3.3 使用Nexus下载jar包)
        • [7.3.3.1 设置Maven本地仓库地址](#7.3.3.1 设置Maven本地仓库地址)
        • [7.3.3.2 设置`<mirror>`标签](#7.3.3.2 设置<mirror>标签)
        • [7.3.3.3 设置Nexus的用户名和密码](#7.3.3.3 设置Nexus的用户名和密码)
        • [7.3.3.4 确定IDEA中Maven指向的本地仓库地址](#7.3.3.4 确定IDEA中Maven指向的本地仓库地址)
        • [7.3.3.5 随意运行一个Maven项目的`clean`](#7.3.3.5 随意运行一个Maven项目的clean)
        • [7.3.3.6 观察本地仓库](#7.3.3.6 观察本地仓库)
        • [7.3.3.7 观察私服上的`maven-public-jk`](#7.3.3.7 观察私服上的maven-public-jk)
      • [7.3.4 使用IDEA部署jar包到Nexus私服](#7.3.4 使用IDEA部署jar包到Nexus私服)
        • [7.3.4.1 设置部署路径](#7.3.4.1 设置部署路径)
        • [7.3.4.2 运行deploy部署命令](#7.3.4.2 运行deploy部署命令)
        • [7.3.4.3 观察私服对应仓库变化](#7.3.4.3 观察私服对应仓库变化)

4. Maven的使用

4.1 下载Maven

官网:http://maven.apache.org/

4.2 配置Maven

Maven解压就是安装。建议将Maven解压到一个没有中文的路径中。

4.2.1 配置环境变量

Maven的核心命令是mvn,这个命令对应的文件是MAVEN_HOME/bin/mvn,打开mvn文件,如下:

可以看到这个mvn命令的使用依赖了JAVA_HOME和MAVEN_HOME两个环境变量。因此这两个环境变量是必须配置的。

  1. JAVA_HOME=JDK的根路径
  2. MAVEN_HOME=Maven的根路径
  3. PATH=%JAVA_HOME%\bin;%MAVEN_HOME%\bin

4.2.2 配置Maven工具参数

MAVAN_HOME/conf/settings.xml文件。

4.2.2.1 配置本地仓库
4.2.2.2 配置远程仓库

找到结束标签,将以下代码贴在其前面:

xml 复制代码
<!--配置阿里远程仓库-->
<mirror>
    <id>aliyunmaven</id>
    <mirrorOf>*</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>

这段配置是 Maven 的镜像(Mirror)设置,用于将 Maven 中央仓库(repo.maven.apache.org)的请求自动重定向到阿里云的 Maven 镜像仓库,以加速依赖下载(尤其在国内访问更稳定、更快)。

4.2.2.3 JDK21自适应构建配置

找到结束标签,在其前面配置以下代码:

xml 复制代码
<profile>
  <id>jdk21</id>
  <activation>
    <activeByDefault>true</activeByDefault>
  </activation>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>21</maven.compiler.source>
    <maven.compiler.target>21</maven.compiler.target>
  </properties>
</profile>

以上配置的作用是:当系统检测到JDK21时,自动使用UTF-8编码,并强制Maven编译器以JDK21版本编译源码和生成字节码(如果不强制的话,maven 会自动通过 JAVA_HOME 环境变量指向的 JDK 进行编译,这样不利于团队协作开发,团队协作开发需要保证 JDK 版本都是一致的。),确保项目在Java 21环境下正确构建(因为我们电脑上安装的 JDK 是 21,因此需要这样配置)。

Maven 本身不包含 Java 编译器:Maven 只是一个构建工具,在编译时,编译插件会调用你本地安装的 JDK 中的 javac 编译器来工作。

4.2.3 IDEA集成Maven

注意:如果使用IDEA集成Maven,则之前配置的MAVEN_HOME、JAVA_HOME、PATH都是没用的。

4.2.3.1 创建一个空的工程(建议)
4.2.3.2 设置空工程的JDK(建议)
4.2.3.3 集成Maven

4.3 手动开发Maven项目

第一步:按照Maven约定的标准目录结构创建Maven项目

plain 复制代码
maven-001
    |-------src
              |--------main
                          |------java
                          |------resources
              |--------test
                          |------java
                          |------resources
    |-------pom.xml

第二步:编写pom文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-001</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--如果配置了这个,那么之前配置的profile就不需要配置了。-->
    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

第三步:编写Java程序

在maven-001/src/main/java目录下新建目录com/jkweilai/maven,创建文件HelloMaven.java。编写如下java代码:

java 复制代码
package com.jkweilai.maven;

public class HelloMaven {
    public static void main(String[] args){
        System.out.println("Hello Maven");
    }
}

第四步:执行编译命令,查看target目录是否生成字节码

一定要在项目的根路径下执行如下命令:

shell 复制代码
mvn clean compile

第五步:运行程序

在dos命令窗口中,将目录切换到target/classes目录下,然后执行以下命令运行程序:

shell 复制代码
java com.jkweilai.maven.HelloMaven

第六步:执行安装命令,查看本地仓库中是否生成jar包

一定要在项目的根路径下执行如下命令:

shell 复制代码
mvn clean install

4.4 IDEA开发Maven Java项目

4.4.1 创建Maven模块

4.4.2 补齐目录(非必须)

test目录中添加一个子目录:resources

4.4.3 添加junit5依赖

xml 复制代码
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.12.2</version>
    <scope>test</scope>
</dependency>

记得点 M 刷新依赖哦。

4.4.4 编写Java程序

java 复制代码
package com.jkweilai;

public class Hello {
    //加法运算
    public int sum(int num1,int num2){
        return num1 + num2;
    }
    //乘法运算
    public int mul(int num1,int num2){
        return num1 * num2;
    }
}

4.4.5 编写测试程序

java 复制代码
package com.jkweilai;

import org.junit.jupiter.api.Test;

// 测试类的类名命名规范:建议以Test结尾。
public class HelloTest {
    /**
     * 一个测试方法就是一个测试用例
     * 测试用例的编写规范
     * 1)访问权限不能是private,其他都可以。
     * 2)方法返回值类型必须是void
     * 3)方法名称自定义,建议以test开头
     * 4)方法不能有参数,有参数会报错
     * 5)使用@Test注解声明是测试方法
     */
    @Test
    public void testSum(){
        Hello  hello = new Hello();
        System.out.println(hello.sum(3,6));
    }
    @Test
    public void testMul(){
        Hello  hello = new Hello();
        System.out.println(hello.mul(3,6));
    }
}

4.5 IDEA开发Maven JavaWeb项目

4.5.1 第一种方式:全部手动配置

4.5.1.1 创建Java Maven模块
4.5.1.2 手动创建目录

对于当前 IDEA 版本来说,经过测试,这个目录的名字必须是 **<font style="color:#DF2A3F;">webapp</font>**才能识别。

4.5.1.3 提供web.xml配置
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                             https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0">
</web-app>
4.5.1.4 添加打包方式和依赖

最后记得点M刷新哦。

4.5.2 第二种方式:在Module上添加Web支持

4.5.2.1 创建Java Maven模块
4.5.2.2 打开项目结构
4.5.2.3 在Module上添加Web支持
4.5.2.4 打包方式war并添加servlet依赖

最后记得点M刷新哦。

4.5.3 第三种方式:通过Maven的webapp原型创建

4.5.3.1 选择Archetype
4.5.3.2 修改web.xml(可选)
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0">
</web-app>
4.5.3.3 添加servlet依赖
xml 复制代码
<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.0.0</version>
    <scope>provided</scope>
</dependency>

4.5.4 编写Servlet并部署项目到Tomcat

java 复制代码
package com.jkweilai.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println("Hello World");
    }
}

4.6 快速拷贝Maven项目

第一步:在硬盘上直接复制粘贴,例如将maven-web-002拷贝为maven-web-003。注意:直接在工程目录下复制,然后还是粘贴到工程目录下,修改名字。

第二步:删除target目录。

第三步:修改pom.xml中的<artifactId>maven-web-003</artifactId>

第四步:打开IDEA工具,在pom.xml文件上右键,然后点击+ Add as Maven Project。

5. Maven的依赖管理

在JAVA开发中,项目的依赖管理是一项重要任务。通过合理管理项目的依赖关系,我们可以有效的管理第三方库,模块的引用及版本控制。而Maven作为一个强大的构建工具和依赖管理工具,为我们提供了便捷的方式来管理项目的依赖。

5.1 什么是依赖范围

Maven的依赖构件包含一个依赖范围的属性。这个属性描述的是三套classpath的控制,即编译、测试、运行。说白了就是添加的jar包起作用的范围。 maven提供了以下几种依赖范围:compile ,test,provided,runtime,system,import。

5.1.1 compile

默认范围(不设置 scope 时,默认就是它),在编译、测试、运行时都需要,会打包。

xml 复制代码
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>6.2.6</version>
  <scope>compile</scope>
</dependency>

5.1.2 test

仅用于测试,在编译和执行测试代码时可用,不会打包。

xml 复制代码
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.12.2</version>
    <scope>test</scope>
</dependency>

5.1.3 provided

已由环境提供,编译和测试时需要,但运行时由 JDK 或容器提供,不会打包。

xml 复制代码
<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.1.0</version>
    <scope>provided</scope>
</dependency>

5.1.4 runtime

测试和运行时需要,但编译时不需要(如 JDBC 驱动)。

xml 复制代码
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.4.0</version>
    <scope>runtime</scope>
</dependency>

5.1.5 system

与 provided 类似(编译和测试时需要,运行阶段不需要,不会打包),但你必须通过 systemPath 显式指定本地系统路径上的 JAR。(建议谨慎使用,因为别人机器上的 jar 包可能不在这个目录下。)

xml 复制代码
<dependency>
  <groupId>com.jkweilai</groupId>
  <artifactId>maven_001</artifactId>
  <version>1.0-SNAPSHOT</version>
  <scope>system</scope>
  <systemPath>D:/repository/com/jkweilai/maven_001/1.0-SNAPSHOT/maven_001-1.0-SNAPSHOT.jar</systemPath>
</dependency>

5.1.6 import

仅用于 <dependencyManagement>,表示从另一个 POM 中导入依赖管理配置。

以下配置的作用是:将 <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">spring-boot-dependencies</font> 这个 POM 文件中 <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);"><dependencyManagement></font> 里的所有依赖配置导入 到当前项目的 <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);"><dependencyManagement></font> 中

xml 复制代码
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.7.0</version>
            <!--type配置必须写,表示导入的是一个pom,而不是jar包-->
            <type>pom</type>
            <!--这个scope也必须写,而且必须这样写-->
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

然后你声明一个实际依赖(不写版本号):

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- 版本由dependencyManagement决定 -->
    </dependency>
</dependencies>
scope 编译 测试 运行 示例
compile(默认) 是 是 是 spring-context
provided 是 是 servlet-api
system 是 是 非maven仓库的本地jar包
runtime 是 是 jdbc驱动
test 编译测试代码时有用 是 junit
import 把另一个POM文件中的依赖版本定义"复制"到当前POM中

5.2 什么是依赖传递

依赖具有传递性。不过在引入依赖时只需要引入直接依赖即可。间接依赖Maven会自动引入。

5.3 依赖范围对依赖传递的影响

scope对依赖传递也有影响。不同的 scope依赖传递效果不同。

5.3.1 主要依赖范围及其传递影响

原则:只要参与打包的都会传递。不参与打包的不会传递。(想想也是:打包的时候里面都没有你,你怎么传递给其他项目!!!)

  1. compile :传递。参与打包
  2. runtime :传递。参与打包
  3. test :不传递 。不参与打包
  4. provided :不传递 。不参与打包
  5. system :不传递 。不参与打包
  6. import :不涉及传递。它本身不是真正的依赖,只是导入依赖管理列表,因此不参与传递性依赖机制。

5.3.2 编写程序测试

创建maven-003工程和maven-004工程

maven-003工程的pom.xml:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-003</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <!--compile:编译 测试 运行 都有效-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.2.7</version>
            <scope>compile</scope>
        </dependency>
        <!--runtime:测试 运行 有效-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.3.0</version>
            <scope>runtime</scope>
        </dependency>
        <!--test:测试 有效-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.12.2</version>
            <scope>test</scope>
        </dependency>
        <!--provided:编译 测试 有效-->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

maven-004工程的pom.xml文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-004</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.jkweilai</groupId>
            <artifactId>maven-003</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

观察依赖范围对依赖传递的影响,可以清楚的看到,只有compile和runtime支持传递:

5.4 Maven是如何解决依赖冲突的

5.4.1 什么是依赖冲突

项目中引入了 a.jar和 b.jar,结果 a.jar关联依赖了一个 my.jar 1.0,b.jar依赖了一个 my.jar 1.1。my.jar 1.0和 my.jar 1.1冲突了。

5.4.2 依赖冲突的解决方案

Maven可以通过以下途径解决依赖冲突。

5.4.2.1 版本锁定

在 Maven 的父工程中,<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);"><dependencyManagement></font> 的核心作用是进行依赖版本的统一锁定。它可以集中管理所有子项目共用的依赖及其版本号,从而确保整个项目体系使用的依赖是一致的。

需要明确的是,<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);"><dependencyManagement></font> 仅仅是一个声明,它本身并不会实际引入这些依赖。

只有当子项目中显式地声明了某个依赖时,该依赖才会被真正引入。此时:

  • 如果子项目没有指定版本号 ,Maven 会自动使用父工程在 <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);"><dependencyManagement></font> 中锁定的版本。
  • 如果子项目明确指定了版本号 ,则会以子项目自己指定的版本为准,覆盖掉父工程中锁定的版本。
  1. 子工程使用父工程锁定的版本号

maven-parent工程中的pom.xml文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>maven-son</module>
    </modules>

    <properties>
        <!--统一版本号-->
        <mysql.version>8.3.0</mysql.version>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!--依赖管理:只声明依赖,但不会将依赖实际的引入项目中。-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <!--使用之前统一声明的版本号-->
                <version>${mysql.version}</version>
                <scope>runtime</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

maven-son工程的pom.xml文件:(注意:maven-son 工程需要创建到 maven-parent 工程内)

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--继承父工程-->
    <parent>
        <groupId>com.jkweilai</groupId>
        <artifactId>maven-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>maven-son</artifactId>

    <dependencies>
        <!--实际引入依赖时,不需要声明版本号,版本号由父工程统一管理-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

通过下图可以看出,子工程使用了父工程中锁定的版本号:

  1. 子工程如果不想使用父工程中锁定的版本号,可以在子工程中指定具体的版本号:

在maven-son子工程的pom.xml文件中指定版本号:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--继承父工程-->
    <parent>
        <groupId>com.jkweilai</groupId>
        <artifactId>maven-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>maven-son</artifactId>

    <dependencies>
        <!--子工程定义了具体的版本号,则不再使用父工程中锁定的版本号。-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.4.0</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

通过下图可以看出,子工程不再使用父工程锁定的版本号:

  1. 父工程不使用标签,则父工程也会引入这个 jar 包。

maven-parent父工程中不再使用<dependencyManagement>:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>maven-son</module>
    </modules>

    <properties>
        <!--统一版本号-->
        <mysql.version>8.3.0</mysql.version>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <!--使用之前统一声明的版本号-->
            <version>${mysql.version}</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

</project>

maven-son子工程不做任何引入,只是继承父工程:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--继承父工程-->
    <parent>
        <groupId>com.jkweilai</groupId>
        <artifactId>maven-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>maven-son</artifactId>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

通过下图可以看出:

5.4.2.2 短路径优先(就近原则)

引入路径短者优先,顾名思义,当一个间接依赖存在多条引入路径时,引入路径短的会被使用。如图

maven-005的pom.xml:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-005</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.3.0</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

maven-006的pom.xml:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-006</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.jkweilai</groupId>
            <artifactId>maven-005</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.4.0</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

结果如下图所示:

5.4.2.3 声明优先

如果存在短路径,则优先选择短路径,如果路径相同的情况下,先声明者优先,POM 文件中依赖声明的顺序决定了间接依赖会不会被使用,顺序靠前的优先使用。如图。

maven-007的pom.xml文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-007</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.4.0</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

maven-008的pom.xml文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-008</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.3.0</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

maven-009的pom.xml文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-009</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.jkweilai</groupId>
            <artifactId>maven-007</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.jkweilai</groupId>
            <artifactId>maven-008</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

效果如下图所示:

5.4.2.4 特殊优先(后来者居上)

同一个pom.xml文件中进行了多次依赖不同版本的jar包,后面的覆盖前面的配置。这种情况比较少见,因为没有人这么傻:

maven-010的pom.xml:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-010</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.3.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.4.0</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

效果如下:

5.4.2.5 可选依赖

maven项目有权利决定自己的直接依赖或者间接依赖是否继续传递给其它的maven项目。如果不想传递,添加以下配置:

xml 复制代码
<optional>true</optional>

maven-011项目的pom.xml:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-011</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.4.0</version>
            <scope>runtime</scope>
            <!--设置mysql驱动不再继续传递给其它项目-->
            <optional>true</optional>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

maven-012项目的pom.xml文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-012</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.jkweilai</groupId>
            <artifactId>maven-011</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

效果如下:

5.4.2.6 排除依赖

当前的maven项目有权利将某个传递过来的依赖排除掉。使用<exclusions>配置。

maven-013项目的pom.xml:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-013</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.4.0</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

maven-014项目的pom.xml文件:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-014</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.jkweilai</groupId>
            <artifactId>maven-013</artifactId>
            <version>1.0-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <groupId>com.mysql</groupId>
                    <artifactId>mysql-connector-j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

效果如下:

可选依赖和排除依赖的区别:

  1. 可选依赖是:我不给。
  2. 排除依赖是:我不要。
  3. 可选依赖的优先级高于排除依赖,若对于同一个间接依赖同时使用排除依赖和可选依赖进行设置,那么可选依赖的取值必须为 false,否则排除依赖无法生效。

5.5 刷新依赖的几种方式

在IDEA中有时候会出现刷新延时的情况,那么需要进行手工刷新依赖:

  1. 点击M刷新按钮。
  2. 点Maven窗口的Reload All Maven Projects。
  3. Build--->ReBuild Project 重新构建项目的同时刷新所有依赖。
  4. 点击本项目的pom.xml文件--->右键--->Maven--->Sync Project 同步项目。
  5. 打开pom.xml文件,全选,剪切,刷新,粘贴,刷新。这属于物理刷新pom.xml文件 。
  6. File->Invalidate Caches...->全选->重启

5.6 资源文件的指定

默认放在java目录下的 .properties文件以及 .xml文件,编译的时候不会自动放到 target 目录下,需要进行以下配置。

xml 复制代码
<build>
    <resources>
        <resource>
            <!--指定java目录下的所有路径下的所有文件-->
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
        <resource>
            <!--指定resources目录下的所有路径下的所有文件-->
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
    </resources>
</build>

6. Maven的继承和聚合

6.1 什么是Maven的继承

当一个项目的多个模块**都依赖于相同版本的 jar 包**,且这些** 模块之间不存在依赖关系**,这就导致同**一个依赖需要在多个模块中重复声明**

在 Java 面向对象中,我们可以建立一种类的父子结构,然后在父类中声明一些字段和方法供子类继承,这样就可以一定程度上消除重复,做到 "一处声明,多处使用"。在 Maven 的世界中,也有类似的机制,它就是 POM 继承。

Maven 在设计时,借鉴了 Java 面向对象中的继承思想,提出了 POM 继承思想。当一个项目包含多个模块时,可以在该项目中再创建一个父模块,并在其 POM 中声明依赖,其他模块的 POM 可通过继承父模块的 POM 来获得对相关依赖的声明。

如图所示:

6.2 packaging必须是pom

父工程的 packaging 必须设为 pom,因为它本身不包含代码或需要构建产物(如 JAR/WAR),而是作为管理角色,用于统一配置(依赖、插件等)和聚合子模块( <modules>)。

父工程的主要职责是作为一个"配置清单"和"聚合器",本身并不包含具体的业务逻辑代码(如Java类),也不需要生成<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">jar</font>或<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">war</font>包来部署或运行。因此,将它的打包类型设置为<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">pom</font>,能清晰地表明它只是一个项目对象模型(Project Object Model)的载体,专门用于管理和组织其他子模块

简单来说:

  • 不打包代码:父工程只做管理,不编译、不生成 JAR/WAR。
  • 核心作用 :通过 <modules> 管理子模块,通过 <dependencyManagement> 统一依赖版本。
  • Maven 规范 :packaging=pom 是 Maven 识别父工程的标志,确保配置正确继承。

如果误设为 jar,Maven 会尝试编译父工程(通常无代码),导致构建失败或逻辑混乱。

6.3 子工程继承父工程的什么

元素 描述
groupId 项目组 ID,项目坐标的核心元素
version 项目版本,项目坐标的核心元素
description 项目的描述信息
organization 项目的组织信息
inceptionYear 项目的创始年份
url 项目的 URL 地址
developers 项目的开发者信息
contributors 项目的贡献者信息
distributionManagement 项目的部署配置
issueManagement 项目的缺陷跟踪系统信息
ciManagement 项目的持续集成系统信息
scm 项目的版本控制系统信息
mailingLists 项目的邮件列表信息
properties 自定义的 Maven 属性
dependencies 项目的依赖配置
dependencyManagement 项目的依赖管理配置
repositories 项目的仓库配置
build 包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等
reporting 包括项目的报告输出目录配置、报告插件配置等

6.4 父工程示例

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--父工程的打包方式必须是pom-->
    <packaging>pom</packaging>

    <!--声明该父项目包含哪些 子模块(子项目):聚合子项目-->
    <modules>
        <module>maven_web</module>
        <module>maven_son</module>
    </modules>

    <properties>
        <!--定义属性,集中管理版本号。便于维护。-->
        <spring.version>6.2.7</spring.version>
        <servlet.version>6.0.0</servlet.version>

        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!--只是定义,并没有真正的添加依赖,子工程根据需要有选择的添加依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <!--使用定义好的属性-->
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>jakarta.servlet</groupId>
                <artifactId>jakarta.servlet-api</artifactId>
                <version>${servlet.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <!--只用于声明插件配置,不会实际执行插件-->
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-maven-plugin</artifactId>
                    <version>11.0.25</version>
                    <configuration>
                        <httpConnector>
                            <port>8080</port>
                        </httpConnector>
                        <webApp>
                            <contextPath>/</contextPath>
                        </webApp>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

6.5 子工程示例

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.jkweilai</groupId>
        <artifactId>maven-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!--可以省略groupId和version,与父工程保持一致-->
    <artifactId>maven_web</artifactId>

    <packaging>war</packaging>

    <!--需要什么依赖添加什么依赖,可以省略版本号,版本由父工程统一管理-->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
        </dependency>
    </dependencies>

    <!--使用jetty插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>11.0.25</version>
                <configuration>
                    <!--子工程可以自定义端口号,不写就使用父工程的-->
                    <httpConnector>
                        <port>8081</port>
                    </httpConnector>
                    <webApp>
                        <contextPath>/</contextPath>
                    </webApp>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

总结:通过继承可以实现子工程沿用父工程的配置。大大减少重复设置。

6.6 什么是Maven的聚合

一键构建:通过聚合项目POM的配置,可以一次性构建所有子模块(不用挨个进目录执行命令)

使用 Maven 聚合功能对项目进行构建时,需要在该项目中额外创建一个的聚合模块,然后通过这个模块构建整个项目的所有模块。聚合模块仅仅是帮助聚合其他模块的工具,其本身并无任何实质内容,对于一个**纯聚合模块**中只有一个 POM 文件,不包含 src 等目录。聚合模块的打包方式packaging也是 pom,可以在其 POM 中通过 modules 下的 module 子元素来添加需要聚合的模块的目录路径,以下是一个**纯聚合模块**的pom:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jkweilai</groupId>
    <artifactId>maven_aggregation</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>../maven-parent</module>
    </modules>

</project>

什么是 **纯聚合项目**,什么是 **非纯聚合项目**?

  • 纯聚合项目 :项目中只有一个pom.xml,其他的都没有,并且在pom.xml文件中只编写了<modules></modules>标签,如下:
  • 非纯聚合项目 :一个项目中既有**聚合部分**,又有**继承部分**,聚合和继承混合,例如之前的maven-parent项目,它的pom.xml文件中既有聚合部分又有继承部分,如下:

理论上可以把"父POM "和"聚合POM "分成两个独立的工程,但实际开发中几乎总是合二为一

6.7 聚合项目的作用

一键构建:通过聚合项目POM的配置,可以一次性构建所有子模块(不用挨个进目录执行命令)

对于之前的这几个项目:maven_aggregation、maven-parent、maven_son、maven_web,其中:

  • maven_aggregation是一个纯聚合项目
  • maven-parent是一个既有聚合又有继承的项目
  • maven_son是maven-parent的子项目
  • maven_web是maven-parent的子项目

在maven_aggregation中:

在maven-parent中:

这个时候执行maven_aggregation项目的install时:

所有被管理的子项目会按照顺序执行各自的install:

7. Maven私服

7.1 什么是私服

Maven 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中央仓库、其他远程公共仓库)。一些无法从外部仓库下载到的构件,也能从本地上传到私服供其他人使用。

Maven 私服其实并不是 Maven 的核心概念,它仅仅是一种衍生出来的特殊的仓库,但这并不代表它不重要,相反由于私服具有降低中央仓库负荷、节省外网带宽、以及提高项目稳定性等优点,使得私服在实际开发过程中得到了相当普遍地使用。建立了 Maven 私服后,当局域网内的用户需要某个构件时,会先请求本地仓库,若本地仓库不存在所需构件,则请求 Maven 私服,将所需构件下载到本地仓库,若私服中不存在所需构件,再去请求外部的远程仓库,将所需构件下载并缓存到 Maven 私服,若外部远程仓库不存在所需构件,则 Maven 直接报错。

7.2 Maven仓库管理器Nexus

7.2.1 什么是Nexus

Nexus 是 Sonatype(中央仓库实际的维护方) 公司发布的一款仓库(Repository)管理软件,常用来搭建 Maven 私服,所以也有人将 Nexus 称为"Maven仓库管理器"。 Sonatype Nexus 是当前最流行,使用最广泛的 Maven 仓库管理器。Nexus 分为开源版和专业版,开源版足以满足大部分 Maven 用户的需求。

7.2.2 Nexus仓库的类型

Nexus默认内置了许多仓库,这些仓库被分为三大类,每种类型的仓库用于存放特定的jar包:

  1. 代理仓库(proxy):缓存下载过的依赖,避免重复从外网拉取。例如Nexus中内置的maven-central库就是一个代理仓库,从远程中央仓库中下载的jar包会被缓存到maven-central这个代理仓库中。
  2. 宿主仓库(hosted):存储本地构建的私有构件,如公司内部开发的 Jar 包。对于宿主仓库来说,包含多个子分类,例如:
    1. Release:存放稳定版本(如Nexus内置的maven-releases仓库),一旦发布到<font style="color:rgb(64, 64, 64);">Release</font>类型的仓库,同一个版本的构件不允许重复部署或覆盖。
    2. Snapshot:存放快照版本(如Nexus内置的maven-snapshots仓库),发布到<font style="color:rgb(64, 64, 64);">Snapshot</font>类型的仓库的构件可以被多次覆盖。
  3. 仓库组(group):将多个仓库合并为一个逻辑入口,简化客户端配置。例如Nexus中内置的maven-public仓库,主要是为了简化配置,这么多仓库不需要都配置,只需要配置一个仓库组就行了。

7.2.3 仓库为什么要分类

分类的目的是 明确职责,优化管理:

  • 隔离环境:区分快照(Snapshot)和正式版(Release),避免混淆。
  • 权限控制:可以为不同仓库设置不同的读写权限(如开发人员可上传 Snapshot,但只有管理员能发布 Release)。
  • 性能优化:代理仓库可以缓存热门依赖,而宿主仓库专注于私有构件。
  • 简化客户端配置:通过仓库组统一暴露仓库,客户端无需关心底层细节。

7.2.4 安装Nexus

7.2.4.1 下载Nexus

下载地址:https://help.sonatype.com/en/download.html

7.2.4.2 解压安装Nexus

下载后解压到一个没有中文的路径下:

打开以上文件夹后,可以看到两个子目录,如下:

7.2.4.3 启动Nexus服务

进入nexus-3.93.2-01\bin目录下:

双击 install-nexus-service.bat批处理文件进行服务的安装。

然后执行这个命令启动服务【以管理员身份运行 】:nexus.exe start SonatypeNexusRepository

等待 2-5 分钟,查看服务是否启动成功:

一定要注意:如果不准备用私服,一定要把这个服务的自动启动修改为手动启动,要不然每次开机都会启动这个服务,这个服务比较耗费内存。

7.2.4.4 访问Nexus

访问地址:http://localhost:8081

第一次登录去这里找密码: nexus-3.93.2-01-win-x86_64\sonatype-work\nexus3,用户名是 admin

登录成功后,第一次要求修改密码,至少八位(这里设置为 12345678),另外为了安全,建议拒绝匿名访问:

端口可以修改,在这个文件中:

7.3 Nexus私服的应用

7.3.1 浏览仓库

7.3.2 设置仓库

7.3.2.1 创建仓库
7.3.2.2 创建代理仓库

阿里云 Maven 镜像:https://maven.aliyun.com/repository/central

设置好以上两项之后,拉到页面底部,点击创建仓库即可。

7.3.2.3 创建宿主仓库:Release

到页面底部点击创建仓库。

7.3.2.4 创建宿主仓库:Snapshot

拉到页面底部,点击创建仓库即可。

7.3.2.5 创建仓库组

拉到页面底部,点击创建仓库即可。

最后所有创建的仓库如下:

7.3.3 使用Nexus下载jar包

7.3.3.1 设置Maven本地仓库地址

修改MAVEN_HOME/conf/settings.xml文件:

xml 复制代码
<localRepository>D:\repository-nexus</localRepository>
7.3.3.2 设置<mirror>标签
xml 复制代码
<mirror>
  <id>nexus-jkweilai</id>
  <mirrorOf>central</mirrorOf>
  <name>nexusjkweilai</name>
  <url>http://localhost:8081/repository/maven-public-jk/</url>
</mirror>

url从这里获取:

7.3.3.3 设置Nexus的用户名和密码

找到 settings.xml文件的 servers标签,添加以下配置:

xml 复制代码
<server>
  <id>nexus-jkweilai</id>
  <username>admin</username>
  <password>12345678</password>
</server>

注意:<id>必须和<mirror>中的<id>保持一致。

7.3.3.4 确定IDEA中Maven指向的本地仓库地址
7.3.3.5 随意运行一个Maven项目的clean

7.3.3.6 观察本地仓库
7.3.3.7 观察私服上的maven-public-jk

7.3.4 使用IDEA部署jar包到Nexus私服

私服Nexus是部署在局域网的,是全公司共享的仓库地址,每个团队都可以将已完成的功能或测试版本发布到私服供别人来使用。

7.3.4.1 设置部署路径

打开要部署的项目的pom.xml文件,设置上传路径

xml 复制代码
<distributionManagement>
    <repository>
        <id>nexus-jkweilai</id>
        <url>http://localhost:8081/repository/maven-releases-jk/</url>
    </repository>
    <snapshotRepository>
        <id>nexus-jkweilai</id>
        <url>http://localhost:8081/repository/maven-snapshots-jk/</url>
    </snapshotRepository>
</distributionManagement>

url从这里拿:

7.3.4.2 运行deploy部署命令
7.3.4.3 观察私服对应仓库变化
  • release项目部署:项目 pom.xml 中需要这样配置 <font style="color:#080808;background-color:#ffffff;"><version>1.0-RELEASE</version></font>,以 <font style="color:#080808;background-color:#ffffff;">RELEASE</font>结尾。
  • snapshot项目部署:项目 pom.xml 中需要这样配置 <font style="color:#080808;background-color:#ffffff;"><version>1.0-SNAPSHOT</version></font>,以 <font style="color:#080808;background-color:#ffffff;">SNAPSHOT</font> 结尾。
相关推荐
顧棟2 小时前
OpenAPI 网关:鉴权 + 流量治理 一体化设计方案与实现
java·spring boot·设计模式
Rain的Java大神之路2 小时前
「设计一个在线文档协同编辑系统」:从 WebSocket、OT/CRDT 到快照回放,一篇讲透这道面试顶流题
java·后端·面试
程序员梅雨2 小时前
【从零开始学习数据仓库 | 第三篇】: Flume——数据采集基石
java·大数据·数据仓库·后端·学习·flume
acd120092 小时前
域名解析缓存带来的隐性故障,很多排查都漏掉了这一层
java·运维·nginx
wuminyu2 小时前
JVM执行引擎学习总结:热点字节码编译成本地机器码
java·linux·c语言·jvm·c++
真上帝的左手2 小时前
2. 编程语言-Java-Spring Boot-JAR
java·spring boot·jar
Jack_hsfs2 小时前
第6章Spring 管理的是对象,还是对象的说明书?
java·后端·spring
十二同学啊3 小时前
Python 工程化详解:项目结构、依赖管理、代码质量、测试与部署
java·开发语言·python