1、Maven是什么?
这个问题非常不重要,或者说不应该上来就问maven是什么,而是直接学习maven怎么用能干什么,学完之后自然就知道了maven是个什么玩意儿,很多技术都是如此。
2、Maven下载
先准备Java环境,安装JDK,配置JDK环境变量。如果是windows系统,去maven官网下载zip版本,解压缩之后配置Maven环境变量就可以使用了。
- **本地仓库地址:**创建一个文件夹当作本地仓库,存放下载的依赖,在conf/setting.xml中修改配置
- **maven镜像:**本地没有的jar包,maven会去官网下载,maven官网在国外所以下载比较慢,可以配置国内的maven镜像,访问速度会快一点。docker也是类似,有镜像服务器。在setting.xml中配置镜像源就行了,可以多配置几个镜像源。
- **pom.xml:**Maven配置文件,学习maven主要就是学习如何读写项目的pom.xml文件
- maven项目结构:
- **target:**编译后的文件放到target中。
3、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.example</groupId>
<artifactId>untitled</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.23</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>26.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
</dependencies>
</dependencyManagement>
</project>
一个简单的pom.xml文件就张上面这个样子。
- modelVersion标签不用管
- groupId、artifactId、version这三个是依赖的坐标信息,类似于空间直角坐标系中的x、y、z可以确定空间中的一个点,者三个标签可以唯一确定一个依赖。(依赖就是别人写的代码,我们直接引入直接拿来用)groupId一般是域名、artifactId一般使用项目名称、version是版本号。
- properties标签这里我们可以去设置JDK版本、字符集等等,还可以去声明依赖的版本,对版本进行统一管理。
- dependencies、dependencie就是引入依赖的标签
- dependencyManagement也是用于引入依赖的标签
4、依赖范围
前面说了,依赖就是别人写的代码,就是我们的代码需要使用别人的代码,我们才会引入相应的依赖。有时候我们会直接业务代码中使用别人的代码。如spring-code;有时候是在测试代码中使用,如Juint。这就是两种不同的范围,在业务代码中使用不到Juint依赖的,所以可以设置Juint依赖只在测试代码中可以被使用。业务代码可以被使用我们称之为运行范围、测试代码中可以被使用称之为测试范围。除此之外还有编译范围,就是要不要编译引入的依赖。打包范围,打包时要不要包含引入的依赖。
如何设计某个依赖的范围呢,maven提供了scope标签,scope需要在dependencie标签中使用。形如:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
下表时不同值对应的作用域:
作用域scope | 编译 | 测试 | 运行 | 打包 | 实例 |
---|---|---|---|---|---|
compile | ![]() | ![]() | ![]() | ![]() | Spring-core |
test | ![]() | ![]() | ![]() | ![]() | junit |
runtime | ![]() | ![]() | ![]() | ![]() | JDBC |
provided | ![]() | ![]() | ![]() | ![]() | Sevlet api |
system | ![]() | ![]() | ![]() | ![]() |
5、maven命令
上图就是maven的一些命令,这些命令是一个生命周期,运行下面的某命令时就会先从clean命令开始一次运行。
- **clean:**清除上一次构建生成的所有文件和目录,比如项目的目标目录(通常是
target
目录),该目录中存放着编译后的类文件、生成的 JAR 包、WAR 包等。通过执行clean
,可以确保每次构建都是从一个干净的状态开始,避免因残留文件导致的构建问题 。 - **validate:**验证项目是否正确并且所有必要的信息都可用。例如,检查项目的 POM 文件是否格式正确,依赖是否配置合理等。但这个阶段不会去下载依赖或者进行实际的构建操作。
- **complie:**编译项目的主源代码(通常是
src/main/java
目录下的 Java 源文件),将 Java 源文件编译成字节码文件(.class
文件),并将编译后的文件放到项目的目标目录(target/classes
)中。 - **test:**使用合适的单元测试框架(如 JUnit)运行测试类(通常在
src/test/java
目录下),对编译后的代码进行单元测试 。但不会对测试代码进行打包等后续操作,只是单纯运行测试来验证功能是否正确。 - **package:**将编译后的代码(包括主代码和可能的资源文件)按照项目指定的打包方式进行打包,比如生成 JAR 包(适用于 Java 类库项目)、WAR 包(适用于 Web 应用项目)或者 EAR 包(适用于企业级 Java 应用项目)等,生成的包会放在目标目录(
target
目录)中。 - **verify:**运行所有检查,验证包是否有效且达到质量标准。例如,检查生成的包是否可以正确解压、包中的元数据是否完整等,还可以结合代码质量检查工具(如 Checkstyle、FindBugs 等)对代码进行进一步的质量验证。
- **install:**将打包好的包安装到本地仓库中,供本地其他项目进行依赖引用。对于 Java 项目,就是将生成的 JAR、WAR 等包安装到本地 Maven 仓库(默认路径在用户主目录下的
.m2/repository
目录),方便在其他项目中通过配置依赖来使用这个项目的功能。 - **site:**生成项目的站点文档,Maven 会根据项目中的各种信息(如项目描述、模块信息、依赖信息、测试报告等)生成一个 HTML 格式的站点,帮助团队成员和外部使用者了解项目的详细情况。
- **deploy:**将最终的包发布到远程仓库(如公司的私服,或者公开的 Maven 中央仓库等),供其他开发人员或者项目进行依赖引用。通常在项目正式发布或者版本更新时执行这个阶段,以便让其他项目可以获取到最新版本的包 。
6、依赖的传递、排除与覆盖
简单讲就是A依赖B,B依赖C,A就自动会依赖C。当然A也可以手动排除C或者覆盖C。
依赖的排除示例(删除exclusions标签依赖就会传递):
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>demo1</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
依赖的覆盖示例:
<dependencies>
<!-- 假设demo1依赖了servlet的某个旧版本 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>demo1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 这里引入一个新的版本就会对旧版本进行覆盖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
这个命令可以查看项目的依赖关系:
mvn dependency:tree
7、Maven继承
一个项目往往会有多个模块,每一个模块都是使用maven进行依赖管理的,也就是每一个模块都是有一个唯一坐标信息的。两个模块之间可以是继承关系,比如S1模块和S2模块都继承了F模块。
那么在F中使用引入的依赖会被S1和S2直接继承。有时候父模块中的依赖并不都是要继承给子模块的。此时父模块可以使用 标签来引入依赖,这样就不会被子模块自动继承了,而子模块可以选择性的进行继承,且不需要指明具体的版本号,因为父模块已经声明过了。
父模块引入servlet依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
子模块选择性继承(不需要指明版本号了):
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
PS:根项目也是可以继承maven配置的。