## Maven ![image-20240229132137502](https://pic.bitday.top/i/2025/03/19/u6rxj1-2.png) ![image-20240229133408054](https://pic.bitday.top/i/2025/03/19/u6tcqw-2.png) Maven仓库分为: - 本地仓库:自己计算机上的一个目录(用来存储jar包) - 中央仓库:由Maven团队维护的全球唯一的。仓库地址:https://repo1.maven.org/maven2/ - 远程仓库(私服):一般由公司团队搭建的私有仓库 POM文件导入依赖的时候,先看本地仓库有没有,没有就看私服,再没有就从中央仓库下载。 ### Maven创建/导入项目 #### **创建Maven项目** ![image-20250307174233390](https://pic.bitday.top/i/2025/03/19/u6u4ni-2.png) 勾选 **Create from archetype**(可选),也可以选择 **maven-archetype-quickstart** 等模版。 点击 Next,填写 GAV 坐标 。 GroupId:标识组织或公司(通常使用域名反写,如 `com.example`) ArtifactId:标识具体项目或模块(如 `my-app`、`spring-boot-starter-web`)。 Version:标识版本号(如 `1.0-SNAPSHOT`、`2.7.3`) #### 导入Maven项目 **(一)单独的Maven项目** 打开 IDEA,在主界面选择 Open(或者在菜单栏选择 File -> Open)。 在文件选择对话框中,定位到已有项目的根目录(包含 `pom.xml` 的目录)。 选择该目录后,IDEA 会检测到 `pom.xml` 并询问是否导入为 Maven 项目,点击 **OK** 或 **Import** 即可。 IDEA 会自动解析 `pom.xml`,下载依赖并构建项目结构。 **(二)在现有Maven项目中导入独立的Maven项目** 在已经打开的 IDEA 窗口中,使用 **File -> New -> Module from Existing Sources...** 选择待导入项目的根目录(其中包含 `pom.xml`),IDEA 会将其导入为同一个工程下的另一个模块(Module)。 它们 看起来在一个工程里了,但**仍然是两个独立的** Maven 模块。 **(三)两个模块属于同一个工程下** 可以用一个父pom进行统一管理! 1.新建一个上层目录,如下,MyProject1和MyProject2的内容拷贝过去。 ```xml ParentProject/ ├── pom.xml <-- 父模块(聚合模块) ├── MyProject1/ <-- 子模块1 │ └── pom.xml └── MyProject2/ <-- 子模块2 └── pom.xml ``` 2.创建父级pom 父模块 `pom.xml` 示例: ```xml 4.0.0 com.example ParentProject 1.0-SNAPSHOT pom //必写 MyProject1 //必写 MyProject2 ``` 3.修改子模块 `pom.xml` ,加上: ```xml com.example ParentProject 1.0-SNAPSHOT ../pom.xml ``` 如果子模块中无需与父级不同的配置,**可以不写**,就自动继承父级配置;若写了同名配置,则表示你想要**覆盖或合并**父级配置。 4.File -> Open选择父级的pom,会自动导入其下面两个项目。 **但是,仅仅这样无法让模块之间产生联动!需要在此基础上进行(四)的操作!** **(四)通过 Maven 依赖引用** 如果你的两个模块之间存在依赖关系(如第一个模块需要使用第二个模块的类)还必须在 MyProject1 的 POM 里**显式声明**对 MyProject2 的依赖。 MyProject1的pom.xml: ```xml com.example ParentProject 1.0-SNAPSHOT ../pom.xml MyProject1 jar com.example MyProject2 ``` **如何打包?** - 在**父 POM 根目录**执行 `mvn clean package`/`mvn clean install`。 - 先构建 MyProject2(因为 MyProject1 依赖它) - 父 POM 自身不产物,模块的 JAR 都在各自的 `target/` 下。 ### Maven坐标 什么是坐标? * Maven中的坐标是 == 资源的唯一标识 == 通过该坐标可以唯一定位资源位置 * 使用坐标来定义项目或引入项目中需要的依赖 ![image-20240302131843540](https://pic.bitday.top/i/2025/03/19/u6ps37-2.png) ### 依赖管理 可以到mvn的中央仓库(https://mvnrepository.com/)中搜索获取依赖的坐标信息 ```xml ch.qos.logback logback-classic 1.2.11 junit junit 4.12 test ``` 更改之后可以在界面上看到一个maven刷新按钮,点击一下就开始联网下载依赖了,成功后可以看到 ![image-20240302133241227](https://pic.bitday.top/i/2025/03/19/u6szry-2.png) #### 排除依赖 A依赖B,B依赖C,如果A不想将C依赖进来,可以同时排除C,被排除的资源**无需指定版本**。 ```xml com.itheima maven-projectB 1.0-SNAPSHOT junit junit ``` #### 依赖范围 | **scope**值 | **主程序** | **测试程序** | **打包(运行)** | **范例** | | --------------- | ---------- | ------------ | ---------------- | ----------- | | compile(默认) | Y | Y | Y | log4j | | test | - | Y | - | junit | | provided | Y | Y | - | servlet-api | | runtime | - | Y | Y | jdbc驱动 | 注意!!!这里的scope如果是`test`,那么它的作用范围在`src/test/java`下,在`src/main/java`下无法导包! ### Maven 多模块工程 父 POM 用 `` 锁版本,子模块按需在 `` 中声明自己用的依赖。对“真正所有模块都要”的依赖,可以放到父 POM 顶层 ``,让它们自动继承。 父 POM(pom.xml): ```xml 4.0.0 com.example parent-project 1.0.0 pom service-a service-b org.springframework.boot spring-boot-starter-web 2.7.3 org.projectlombok lombok 1.18.20 org.projectlombok lombok provided ``` 子pom ```xml 4.0.0 com.example parent-project 1.0.0 ../pom.xml service-a jar org.springframework.boot spring-boot-starter-web ``` 父pom的`pom`表示它只是一个 POM 模块,不会产出任何可执行的 JAR。 子pom的`../pom.xml`告诉 Maven 去哪个相对路径找父 POM 文件 注意:如果子模块A依赖于B模块,那么B模块中的依赖会传递给A,比如B中引入了`org.apache.httpcomponents`,那么A模块的类中可以直接import这个库。反过来不行!大坑! ### Maven生命周期 主要关注以下几个: • clean:移除上一次构建生成的文件 (Target文件夹) • compile:编译 `src/main/java` 中的 Java 源文件至 `target/classes` • test:使用合适的单元测试框架运行测试(junit) • package:将编译后的文件打包,如:jar、war等 • install:将打包后的产物(如 `jar`)安装到本地仓库 **后面的生命周期执行的时候会自动执行前面所有生命周期!** #### compile: ```text src/ ├── main/ │ ├── java/ │ │ └── com/ │ │ └── example/ │ │ └── App.java │ └── resources/ │ ├── application.yml │ └── static/ │ └── logo.png └── test/ ├── java/ │ └── com/ │ └── example/ │ └── AppTest.java └── resources/ └── test-data.json 映射到 target/ 后: target/ ├── classes/ ← 主代码和资源的输出根目录 │ ├── com/ │ │ └── example/ │ │ └── App.class ← 编译自 src/main/java/com/example/App.java │ ├── application.yml ← 复制自 src/main/resources/application.yml │ └── static/ │ └── logo.png ← 复制自 src/main/resources/static/logo.png └── test-classes/ ← 测试代码和测试资源的输出根目录 ├── com/ │ └── example/ │ └── AppTest.class ← 编译自 src/test/java/com/example/AppTest.java └── test-data.json ← 复制自 src/test/resources/test-data.json ``` #### test: **扫描** `src/test/java` 下所有符合默认命名规则的测试类: - `**/Test*.java` - `**/*Test.java` - `**/*TestCase.java` **编译** 这些测试类到 `target/test-classes`。 **逐个执行**(默认是串行)所有这些编译后的测试类。 #### package: 打包失败的把test步骤去掉! ![image-20250514125309214](https://pic.bitday.top/i/2025/05/14/kq2fpz-0.png)