Maven
安装
介绍
Maven 是意第绪语,意思 是 知识的积累者,最初是为了简化 Jakarta Turbine 项目中的构建过程。
随着发展,成为了Java项目的项目构建和依赖管理工具;
学习Maven就是学习他的以下两个核心功能
- 项目构建:包含的核心环节有
- 项目创建、编译、测试、打包、部署、运行等过程
- 依赖管理:包含的核心功能有
- 项目关联jar包的下载、导入、冲突解决、依赖传递等
下载
官网:https://maven.apache.org/
镜像加速
maven 默认会从中央仓库下载项目依赖,比较慢,可以配置为国内 aliyun 等镜像源,方便快速下载
修改 conf/settings.xml
,搜索 mirrors
标签,替换为如下内容
<mirrors> <mirror> <id>alimaven</id> <mirrorOf>central,jcenter</mirrorOf> <name>aliyun maven</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> </mirrors>
|
验证:使用命令:mvn help:effective-settings
基础
validate:验证项目是否正确并且所有必要的信息都可用
compile:编译项目的源代码
test:运行单元测试代码。测试代码不应该要求打包或部署
package:获取已编译的代码并将其打包成可分发的格式,例如 JAR。
verify:对集成测试的结果进行任何检查,以确保满足质量标准
install:将包安装到本地存储库中,作为本地其他项目的依赖项
deploy:将最终包复制到远程存储库以与其他开发人员和项目共享。
核心概念 - GAV坐标
GAV:项目的唯一坐标;GAV是三个字母组合,分别代表如下:
- G****roupId:组织名;一般用公司域名反写。如: com.lfy、org.apache、io.spring 等
- A****rtifactId:模块名;也就是项目名。如:book-store、mall、order-service 等
- V****ersion:版本号;项目的版本。如:1.0.1、5.2.19.RELEASE、17-lts 等
gav具有全球唯一性,表示某个公司的某个版本的某个项目
原理:maven根据坐标去下载指定的jar包,保存到本地;
- 注意:相同的jar包其实只有一份,就是在本地仓库保存着。每个项目只是引用这个包,如果这个包之前下载过了,别的项目再要引用,就不用下载了
中央仓库:https://mvnrepository.com/ ;中央仓库一般在国外,比较慢,所以我们需要配置国内镜像
扩展:Version推荐的命名规范
版本号的格式为 X.Y.Z (又称 Major.Minor.Patch),递增的规则为
- X 表示主版本号,当 API 的兼容性变化时,X 需递增
- Y 表示次版本号,当增加功能时(不影响 API 的兼容性),Y 需递增
- Z 表示修订号,当做 Bug 修复时(不影响 API 的兼容性),Z 需递增
还可以加入一些常见修饰词;如下:
- Alpha:内部版本
- beta:测试版
- SNAPSHOT:快照版
- enhance:增强版
- rc:即将作为正式版发布
- GA:General Availability即正式版
- lts:长期维护版本
- release:发行版
- final:最终定稿版
- stable:稳定版
- standard:标准版
- ultimate:旗舰版
- upgrade:升级版
核心概念 - POM
POM全称:Project Object Model:项目对象模型
一个项目的信息被表示为一个 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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.lfy</groupId> <artifactId>zpro</artifactId> <version>1.0-SNAPSHOT</version> <name>z-project</name> <packaging>war</packaging>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>11</maven.compiler.target> <maven.compiler.source>11</maven.compiler.source> <junit.version>5.9.2</junit.version> </properties>
<dependencies> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency>
<dependency> <groupId>jakarta.servlet.jsp</groupId> <artifactId>jakarta.servlet.jsp-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>3.0.2</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jakarta.servlet.jsp.jstl</artifactId> <version>3.0.1</version> </dependency>
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency>
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.36</version> <scope>provided</scope> </dependency>
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.4.0</version> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.25</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> </plugin> </plugins> </build> </project>
|
实操
IDEA 整合 Maven
IDEA 其实有内置maven;如果网络好的情况下,我们可以不用给idea配置我们下载的Maven
IDEA 整合 maven,主要是使用我们下载好的maven的配置文件和镜像仓库地址
整合流程:**File --> New Projects Setup --> Settings For New Projects --> Build Tools
**
maven项目结构
普通项目结构
Maven - 普通项目结构
- src: 源码文件夹
- main: 主程序文件夹
- java: java代码文件夹
- resources:配置文件夹
- test:测试程序文件夹
- java: java测试代码文件夹
- resources:测试配置文件夹
- target:编译后文件夹
- pom.xml:Maven项目核心文件
pom.xml 解读
modelVersion:pom模型版本,固定写法; groupId:组织名: 一把公司网址反写 artifactId:模块名:一般就是项目名 version:版本号:按照版本起名规范编写
name:项目显示名 description:项目描述 packaging:项目打包方式;pom、jar、war; 默认是 jar properties:项目属性设置
......
|
依赖管理
什么是依赖:就是项目开发期间需要引入别人写好的项目功能,我们把这个称为项目A依赖项目B
依赖导入
项目中如果需要别的依赖,就需要在pom文件中导入别的依赖;具体操作流程如下:
- 编写 dependencies 标签
- 使用 dependency 标签
- 填写依赖 GAV 坐标
- 第三方包:去 https://mvnrepository.com/ 搜索jar;复制gav坐标
- 自己写的包:写 gav 即可
依赖传递
如果我们导入如下依赖;会发现项目中引入了一堆其他依赖;这个就叫依赖的传递
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>6.1.11</version> </dependency>
|
如果存在这样的引用关系:A -> B -> C;那么 A -> C
解释:项目引入某个依赖,这个依赖的依赖都会被全部引入
创建多个maven工程,测试传递性
- 路径不同:最短路径原则(就近原则)
- 路径相同:先声明者优先(就近原则)
我们可以通过设置依赖范围,从而实现让这个依赖只在指定范围内生效
maven项目依赖生效分为三个时期:编译期、测试期、运行期;
scope控制依赖在哪个时期会被加载和生效,默认取值为 compile(全时期);
注意:
- runtime 常用complie 代替,而compile是默认可以不用配置,也就是所一般只配test和provided;
- 从中央仓库搜索并复制的依赖,无需管scope,默认设置好。比如(servlet-api、junit)
特别注意:非 compile和runtime 的依赖不会传递
依赖排除
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>6.1.11</version> <exclusions> <exclusion> <groupId>io.micrometer</groupId> <artifactId>micrometer-observation</artifactId> </exclusion> </exclusions> </dependency>
|
可选依赖
<dependency> <groupId>com.atguigu</groupId> <artifactId>app1</artifactId> <version>1.0.0</version> <optional>true</optional> </dependency>
|
属性抽取
我们一般会把依赖的版本号,抽取成属性,然后进行统一管理;
如下:可以实现的效果是:修改一处版本号,凡是引用此属性的版本号都会一起修改。
<properties> <spring.version>6.1.11</spring.version> </properties>
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> </dependencies>
|
生命周期
重点:执行任何一个生命周期阶段,之前的生命周期阶段都会被执行
validate 验证项目是否正确,所有必要的信息可用 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 使用合适的单元测试框架运行测试。测试代码不会被打包或部署 prepare-package package 接受编译好的代码,打包成可发布的格式,如JAR、WAR、zip pre-integration-test integration-test post-integration-test verify 对集成测试的结果执行任何检查,以确保满足质量标准 install 将包安装至本地仓库,以让其它项目依赖。 deploy 将最终的包复制到远程的仓库
|
插件&目标
插件:生命周期与插件是相互绑定的。
执行生命周期命令时,需要通过插件来完成。compile 和test-compile 都通过同一个插件完成的。
目标: 就是插件所需要做的事情,
例如:
- maven-compiler-plugin 既可以执行compile,也可以执行testCompile
- compile和testCompile是maven-compiler-plugin插件的两个功能;
- 当maven-compiler-plugin插件执行compile的时候,那么compile就是插件的一个最终目标;
模块化
继承
maven的项目可以产生父子继承关系;如果A是B的子项目,则会产生如下的效果
- 依赖继承:子继承父依赖
- 插件继承:子继承父插件
- 依赖管理:父管理子依赖
- 版本锁定:父锁定版本
- 属性继承:子继承父属性
- 多继承:使用import,一个模块就可以继承更多的其他模块也行
聚合
子项目继承父项目,那么父项目就聚合了子项目;副项目可以统一管理所有的子项目
使用聚合;就得创建多个模块,然后在父项目中使用 modules 聚合多个模块;聚合后产生如下效果
- 模块顺序:自动打包顺序
- 统一编译
- 统一打包