Maven 是一款用于管理和构建 java 项目的工具
Maven 可以方便快捷的管理项目依赖的资源 (jar 包),避免版本冲突问题;提供标准、统一的项目结构;标准跨平台的自动化项目构建方式
安装
在官网下载后解压,然后配置本地仓库,修改 conf/setting.xml
中的 <localRepository>
为一个指定目录
1
2
<!-- 例如本地库在 D:\develop\maven_repo -->
<localRepository>D:\develop\maven_repo</localRepository>
配置阿里云私服镜像,修改 conf/setting.xml
中的 <mirror>
标签,添加子标签
1
2
3
4
5
6
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
配置环境变量:MAVEN_HOME
为 maven 解压目录,并将其 bin 目录加入 PATH 环境变量
测试安装完成:在命令行输入 mvn -v
查看输出
依赖配置
依赖:指当前项目运行所需要的 jar 包,一个项目中可以引入多个依赖
配置步骤:
- 在 pom.xml 中编写
<dependencies>
标签 - 在
<dependencies>
标签中使用<dependency>
引入坐标 - 定义坐标的 groupId, artifactId, version
- 刷新配置,引入新加入的坐标
1
2
3
4
5
6
7
8
<!-- 例如引入 logback -->
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
可以到 https://mvnrepository.com/ 查找依赖坐标信息
依赖传递
依赖具有传递性
- 直接依赖:在当前项目中通过依赖配置建立的依赖关系
- 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源
当添加依赖时,若此包依赖其他包,将自动添加相关包
当然,若某包的子包并不需要,可以排除依赖 (指主动断开依赖的资源,被排除的资源无需指定版本)
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 例如排除某项目的 junit -->
<dependency>
<groupId>com.yexca</groupId>
<artifactId>maven-project</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
依赖范围
依赖的 jar 包,默认可以在任何地方使用,可以通过 <scope>...</scope>
设置其作用范围:
- 主程序范围有效 (main 文件夹范围内)
- 测试程序范围有效 (test 文件夹范围内)
- 是否参与打包运行 (package 指令范围内)
scope 值 | 主程序 | 测试程序 | 打包 (运行) | 范例 |
---|---|---|---|---|
compile (默认) | Y | Y | Y | log4j |
test | - | Y | - | junit |
provided | Y | Y | - | servlet-api |
runtime | - | Y | Y | jdbc 驱动 |
1
2
3
4
5
6
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
生命周期
Maven 的生命周期就是为了对所有的 maven 项目构建过程进行抽象和统一
Maven 中有 3 套相互独立的生命周期:
- clean:清理工作
- default:核心工作,如:编译、测试、打包、安装、部署等
- site:生成报告、发布站点等
其中每套生命周期包含一些阶段 (phase) ,阶段是有顺序的,后面的阶段依赖于前面的阶段
clean
- pre-clean
- clean:移除上一次构建生成的文件 (target 文件夹)
- post-clean
default
- validate
- initialize
- generate-sources
- process-sources
- generate-resources
- process-resources
- compile:编译项目源代码
- process-classes
- generate-test-sources
- process-test-sources
- generate-test-resources
- process-test-resources
- test-compile
- process-test-classes
- test:使用合适的单元测试框架运行测试 (junit)
- prepare-package
- package:将编译后的文件打包,如 jar、war 等
- verify
- install:安装项目到本地仓库
- deploy
site
- pre-site
- site
- post-site
- site-deploy
在同一套生命周期中,当运行后面的阶段时,前面的阶段都会运行
分模块设计
分模块设计我们在进行项目设计阶段,就可以将一个大的项目拆分成若干个模块,每一个模块都是独立的,如果我们需要用到另外一个模块的功能,我们直接依赖模块就可以了
可以把一些通用的实体类或工具类单独作为一个模块,若某一模块需要使用,直接引入对应的依赖即可
方便项目的管理维护、扩展,也方便模块间的相互调用,资源共享
继承
像 Lombok 依赖,可能项目中的每个模块都会使用,每个模块都声明一次相当繁琐,可以通过继承解决这个问题
继承关系
创建一个父工程,将模块共有的依赖都提取到父工程进行配置,只要子类继承了父工程,依赖也会继承下来,这样就无需在各个子工程中进行配置了
继承描述的是两个工程间的关系,与 java 中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承,可以简化依赖配置、统一管理依赖
1
2
3
4
5
6
7
<!--指定父工程-->
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<relativePath>....</relativePath>
</parent>
如果是 JavaWeb 开发,可以让父工程继承 spring-boot-starter-parent,其他模块继承该父工程
一般情况下,在文件结构中,子工程为父工程子级
以下为例子
- 父工程的打包方式为 pom
1
2
3
4
5
6
7
8
9
10
11
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.yexca</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
Maven打包方式:
- jar:普通模块打包,SpringBoot 项目基本都是jar包 (内嵌 tomcat 运行)
- war:普通 web 程序打包,需要部署在外部的 tomcat 服务器中运行
- pom:父工程或聚合工程,该模块不写代码,仅进行依赖管理
- 子工程指定父工程
1
2
3
4
5
6
7
8
9
10
11
12
13
<parent>
<groupId>net.yexca</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 指定父工程的pom文件的相对位置(如果不指定,将从本地仓库/远程仓库查找该工程) -->
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>
<!-- <groupId>net.yexca</groupId>
- 因为自动继承父工程,可以省略
-->
<artifactId>tlias-utils</artifactId>
<version>1.0-SNAPSHOT</version>
- 父工程中配置共有依赖
1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
版本锁定
某依赖部分模块需要,部分模块不需要,可以在父级中管理依赖的 version,方便管理与修改
可以通过 <dependencyManagement>
标签管理依赖版本
父工程
1
2
3
4
5
6
7
8
9
10
11
<!--统一管理依赖版本-->
<dependencyManagement>
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
</dependencyManagement>
子工程
1
2
3
4
5
6
7
8
9
10
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<!-- <version>0.9.1</version>
- 因为父工程指定了版本,不需要填写
-->
</dependency>
</dependencies>
父工程的
<dependencyManagement>
配置只管理版本,不会将依赖引入子工程。只有在子工程引入才会引入,只是引入时无需指定版本号而
<dependencies>
会把依赖引入子工程
属性配置
也可以通过自定义属性及属性引用的形式,在父工程中将依赖的版本号进行集中管理维护
自定义属性:
1
2
3
<properties>
<lombok.version>1.18.24</lombok.version>
</properties>
引用属性:
1
2
3
4
5
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
于是可以在父工程中将所以的版本号,集中管理维护
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<lombok.version>1.18.24</lombok.version>
<jjwt.version>0.9.1</jjwt.version>
<aliyun.oss.version>3.15.1</aliyun.oss.version>
<jaxb.version>2.3.1</jaxb.version>
<activation.version>1.1.1</activation.version>
<jaxb.runtime.version>2.3.3</jaxb.runtime.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<!--统一管理依赖版本-->
<dependencyManagement>
<dependencies>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!--阿里云OSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun.oss.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>${jaxb.runtime.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
若想要修改依赖的版本,只需要在父工程的自定义属性,修改相应属性值即可
聚合
若一个模块依赖另一个模块,打包该模块前需要先将其他模块 install 到本地仓库,然后再打包。如果依赖的模块很多,那么需要执行的操作过于繁琐
通过 maven 的聚合就可以轻松实现项目的一键构建 (清理、编译、测试、打包、安装等)
- 聚合:将多个模块组织成一个整体,同时进行项目的构建
- 聚合工程:一个不具有业务功能的“空”工程 (有且仅有一个pom文件。一般来说,继承关系中的父工程与聚合关系中的聚合工程是同一个)
- 作用:快速构建项目 (无需根据依赖关系手动构建,直接在聚合工程上构建即可)
可以在聚合工程中通过 <modules>
设置当前聚合工程所包含的子模块的名称
1
2
3
4
5
6
7
<!--聚合其他模块-->
<modules>
<!-- 工程路径 -->
<module>../tlias-pojo</module>
<module>../tlias-utils</module>
<module>../tlias-web-management</module>
</modules>
之后进行编译、打包、安装操作只在聚合工程上即可,其他工程会自动同步操作
继承 | 聚合 | |
---|---|---|
作用 | 继承用于简化依赖配置、统一管理依赖 | 聚合用于快速构建项目 |
相同点 | 打包方式均为 pom,通常制作到同一 pom | 均属于设计型模块,无实际内容 |
不同点 | 继承是在子模块中配置关系 父模块无法感知哪些子模块继承了自己 |
聚合是在聚合工程中配置关系 聚合可以感知到参与聚合的模块有哪些 |
私服
私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的中央仓库,用于解决团队内部的资源共享与资源同步问题
如果在项目中需要使用其他第三方提供的依赖,如果本地仓库没有,会自动连接私服下载,如果私服没有,私服此时会自动连接中央仓库,去中央仓库中下载依赖,然后将下载的依赖存储在私服仓库及本地仓库中
私服一般一个公司一台,不用自己配置
私服仓库与项目版本
私服仓库说明:
- RELEASE:存储自己开发的 RELEASE 发布版本的资源
- SNAPSHOT:存储自己开发的 SNAPSHOT 发布版本的资源
- Central:存储的是从中央仓库下载下来的依赖
项目版本说明:
- RELEASE (发布版本):功能趋于稳定、当前更新停止,可以用于发行的版本,存储在私服中的RELEASE仓库中
- SNAPSHOT (快照版本):功能不稳定、尚处于开发中的版本,即快照版本,存储在私服的SNAPSHOT仓库中
配置
设置私服的访问用户名与密码,在 Maven 安装目录的 conf/settings.xml
的 servers 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
<servers>
<server>
<id>maven-releases</id>
<username>admin</username>
<password>admin</password>
</server>
<server>
<id>maven-snapshots</id>
<username>admin</username>
<password>admin</password>
</server>
</servers>
设置私服依赖下载的仓库组地址,文件同上,mirrors 与 profiles 标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<mirrors>
<mirror>
<id>maven-public</id>
<mirrorOf>*</mirrorOf>
<url>http://127.0.0.1:8081/repository/maven-public/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>allow-snapshots</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>maven-public</id>
<url>http://127.0.0.1:8081/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
pom 文件配置上传地址,在父工程中配置即可
1
2
3
4
5
6
7
8
9
10
11
12
13
<distributionManagement>
<!-- release版本的发布地址 -->
<repository>
<id>maven-releases</id>
<url>http://127.0.0.1:8081/repository/maven-releases/</url>
</repository>
<!-- snapshot版本的发布地址 -->
<snapshotRepository>
<id>maven-snapshots</id>
<url>http://127.0.0.1:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
配置完成后,执行父工程的 deploy 生命周期即可将项目发布到私服仓库