Maven 使用手册【原创·个人私用】
Maven 是干嘛的?
通过Maven,可以帮助我们做:
- 项目的自动构建,包括代码的编译、测试、打包、安装、部署等操作。
- 依赖管理,项目使用到哪些依赖,可以快速完成导入。
就是我们不需要手动导入 Jar 包了,直接通过 Maven 的配置文件 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">
<!-- 定义 maven 配置文件需要的 标签元素 -->
<modelVersion>4.0.0</modelVersion>
<!-- 组别 => 类似于包名,但实际上我们称为项目组名,它是我们虚拟定义的 -->
<groupId>org.example</groupId>
<!-- 项目的名字 -->
<artifactId>MavenTest</artifactId>
<!-- 项目的版本号, SNAPSHOT 表示快照 => 意思是正在开发中 -->
<version>1.0-SNAPSHOT</version>
<!--通过将 <packaging> 元素设置为 pom,Maven 就知道该项目是一个聚合项目,不会生成任何构件,而是根据子项目的定义进行构建和管理。-->
<!--<packaging>pom</packaging>-->
<!-- <modules>-->
<!-- <module>SonA</module>-->
<!-- </modules>-->
<properties>
<!--意思是 JDK 用的 1.8-->
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!--依赖、第三方库-->
<dependencies>
<dependency>
<!--通过 groupId、artifactId、version 三属性(Maven 坐标来下载依赖)-->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<!--此依赖是作用域范围-->
<scope>provided</scope>
<!--<type>jar</type>-->
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
<!--一些依赖它会导入 其它的前提依赖、但我们还不想导入它!用 exclusions -->
<exclusions>
<exclusion>
<!--比如我们不想导入 junit 携带过来的 junit-jupiter-engine -->
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<!--标记为该依赖为 可选依赖,即不会下载和导入此依赖!-->
<!--当值为 false 才会下载和导入此依赖!-->
<optional>true</optional>
</dependency>
</dependencies>
<!--打包用到的 插件!Maven 其实也可以远程下载一些 插件 ~ -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.test.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</project>
在 Maven 中,项目的模型由一个 POM(Project Object Model)文件定义,该文件是一个 XML 文件,描述了项目的结构、依赖关系、构建配置等信息。<modelVersion>
元素指定了使用的 POM 模型的版本。
在现代的 Maven 项目中,通常使用的是 Maven 4.0.0 的模型版本。这个版本的模型定义了一套规范,用于描述 Maven 项目的基本结构和配置。通过指定 <modelVersion>4.0.0</modelVersion>
,Maven 就知道使用的是这个版本的模型,从而按照相应的规范解析和处理项目的 POM 文件。
作用域讲解
我们着重来讲解一下scope
属性,它决定了依赖的作用域范围:
- compile :为默认的依赖有效范围。如果在定义依赖关系的时候,没有明确指定依赖有效范围的话,则默认采用该依赖有效范围。此种依赖,在编译、运行、测试时均有效。
- provided :在编译、测试时有效,但是打包的时候不会打包进去!也就是说,打包的项目在运行时,可能不需要此依赖,比如我们上面的Lombok,我们只需要在编译阶段使用它,编译完成后,实际上已经转换为对应的代码了,因此Lombok也就不需要打包出去了。
- runtime :只在运行、测试的时候有效,即运行和测试的时候才会去用这个依赖。
- test :只在测试时有效,例如:JUnit,我们一般只会在测试阶段使用JUnit,而实际项目运行时,我们就用不到测试了,那么我们来看看,导入JUnit的依赖:
- system:作用域和provided是一样的,但是它不是从远程仓库获取,而是直接导入本地Jar包
<dependency>
<groupId>javax.jntm</groupId>
<artifactId>lbwnb</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>C://学习资料/4K高清无码/test.jar</systemPath>
</dependency>
Maven 项目资源文件
在Maven 项目中,所有的资源文件,包括配置文件都得放在 resource
文件夹。比如说,mybatis.xml 就得放在 resource 文件夹下 这也是为了方便统一管理
然后只要使用 Resources.getResourceAsStream(resource文件夹下的路径即可,属于相对路径)
就可以拿到这个 文件的流
public class MainTest {
//因为配置文件位于内部,我们需要使用Resources类的getResourceAsStream来获取内部的资源文件
private static SqlSessionFactory factory;
//在JUnit5中@Before被废弃,它被细分了:
@BeforeAll // 一次性开启所有测试案例只会执行一次 (方法必须是static)
// @BeforeEach 一次性开启所有测试案例每个案例开始之前都会执行一次
@SneakyThrows
public static void before(){
factory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsStream("mybatis.xml"));
}
@DisplayName("Mybatis数据库测试") //自定义测试名称
@RepeatedTest(3) //自动执行多次测试
public void test(){
try (SqlSession sqlSession = factory.openSession(true)){
TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
System.out.println(testMapper.getStudentBySid(1));
}
}
}
上方的一些注解,是 Junit5 支持的用法。可以适当的了解一下 ~
Maven 继承
一个Maven项目可以继承自另一个Maven项目,比如多个子项目都需要父项目的依赖,我们就可以使用继承关系来快速配置。
我们右键左侧栏,新建一个模块,来创建一个子项目:
<?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">
<!--指定它的父亲项目叫啥名、属于哪个根项目/组别-->
<parent>
<artifactId>MavenTest</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!--然后只需要 指明子项目的 名字就完事了 ~ -->
<artifactId>ChildModel</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
我们还可以让父Maven项目统一管理所有的依赖,包括版本号等,子项目可以选取需要的作为依赖,而版本全由父项目管理,我们可以将dependencies
全部放入dependencyManagement
节点,这样父项目就完全作为依赖统一管理。
所以说 父项目 pom.xml 就可以这样写:
<!--放到 dependencyManagement 标签中的 dependencies 依赖,就都可以管理了-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
</dependencyManagement>
然后 子 pom.xml 就不会实现 不写依赖就能用了!而是必须得 写依赖的声明,当 没有写版本号 <version>
的时候,就代表这个 依赖是从 父 pom.xml <dependencyManagement> 标签内 继承过来的依赖!
<project>
<parent>
<!-- 父 POM 的坐标 -->
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- 其他依赖项 -->
</dependencies>
</project>
Maven 常用命令
我们可以看到在IDEA右上角Maven板块中,每个Maven项目都有一个生命周期,实际上这些是Maven的一些插件,每个插件都有各自的功能,比如:
clean
命令,执行后会清理整个target
文件夹,在之后编写Springboot项目时可以解决一些缓存没更新的问题。validate
命令可以验证项目的可用性。compile
命令可以将项目编译为.class文件。install
命令可以将当前项目安装到本地仓库,以供其他项目导入作为依赖使用verify
命令可以按顺序执行每个默认生命周期阶段(validate
,compile
,package
等)
Maven 测试项目
通过使用test
命令,可以一键测试所有位于test目录下的测试案例,请注意有以下要求:
- 测试类的名称必须是以
Test
结尾,比如MainTest
- 测试方法上必须标注
@Test
注解,实测@RepeatedTest
无效
这是由于JUnit5比较新,我们需要重新配置插件升级到高版本,才能完美的兼容Junit5:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!-- JUnit 5 requires Surefire version 2.22.0 or higher -->
<version>2.22.0</version>
</plugin>
</plugins>
</build>
现在@RepeatedTest
、@BeforeAll
也能使用了。
因为@RepeatedTest
、@BeforeAll
都是 JUnit 5的
Maven 项目打包
在打包之前也会执行一次test命令,来保证项目能够正常运行,当测试出现问题时,打包将无法完成,我们也可以手动跳过,选择执行Maven目标
来手动执行Maven命令,输入mvn package -D maven.test.skip=true
来以跳过测试的方式进行打包。或者是,直接 双击 最上方工具栏 那里的 build 命令,也可以直接进行 打包!然后你就能在 target 目录下就能看到 .jar 这个执行文件了!
deploy
命令用于发布项目到本地仓库和远程仓库,一般情况下用不到,这里就不做讲解了。site
命令用于生成当前项目的发布站点,暂时不需要了解。