Maven 是什么
Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供构建和依赖管理支持的工具。
什么是 Maven 的构建
Maven 的构建包括 clean(清除)、 compile(编译)、 test(测试)、 site(报告)、 package(打包)、 install(安装)、 deploy(部署),各自的具体作用如下:
- clean(清除):清除上一次的构建信息,为下一次构建做准备,不执行该步骤也是可以的,会自动覆盖。
- compile(编译):将 Java 源文件编译成字节码 Class 文件。
- test(测试):运行提前准备好的测试程序,执行 test 目录下的测试用例。
- site(报告):记录测试结果。
- package(打包):就是我们常用的 jar 包、war 包。
- install(安装):把一个 Maven 项目打包 jar 包后存入到 Maven 仓库。
- deploy(部署):把 jar 包部署到 Nexus 私服上,可以上其他开始人员使用。
什么是 Maven 的依赖
Maven 的依赖功能是是我们使用 Maven 的主要原因,我们使用 Maven 的依赖管理,Maven 的依赖管理帮我们解决了 jar 包的下载,同时可以把项目中的依赖进行传递或把某些不需要依赖进行排除。
Maven 的下载安装
Maven 下载解压后如下:
配置本地 Maven 仓库,Maven 默认的本地仓库目录是:用户目录/.m2/repository,一般都会自己指定一个本地仓库目录,自己指定 Maven 本地仓库目录需要修改 conf 目录下的 settings.xml 文件,如下:
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>D:\tool\maven\repository</localRepository>
Maven 的坐标(dependency)
Maven 中的坐标使用三个向量 groupId、artifactId、version 在 Maven 的仓库中唯一的定位到一个 jar 包。
- groupId:一般是公司的域名或者简称,例如:com.alibaba。
- artifactId:一般是项目或者模块的名称,例如:order-server。
- version:版本号。
dependency 除了以上三个属性还有一个属性 scope,scope 表示依赖的范围,scope 的值有、compile、provide、runtime、test、system,具体如下:
- compile:编译范围,该范围为默认依赖范围,编译范围的依赖会用在编译,测试,运行,由于运行时需要,所以编译范围的依赖会被打包。
- provide:provied 依赖只有当 JDK 或者 Tomcat 已提供该依赖之后才使用,provide 依赖在编译和测试时需要,在运行时不需要,因为运行时候 JDK 或者 Tomcat 已经提供了。
- runtime:runtime 依赖在运行和测试系统时需要,但在编译时不需要,由于运行时需要,所以 runtime 范围的依赖会被打包。
- test:test 范围依赖在编译和运行时都不需要,只在测试编译和测试运行时需要,因此 test 范围的依赖不会被打包。
- system:system 范围依赖与 provide 类似,但是必须显示的提供一个对于本地系统中 jar 文件的路径,一般不推荐使用。
Maven 标签在 pom 文件中的使用
一个简单的项目的 pom 文件的核心配置如下:
<!-- 当前 Maven 项目的坐标 -->
<groupId>com.demo</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<!-- 当前 Maven 项目的打包方式 有 jar war pom 三种方式-->
<!-- jar:表示这个项目是一个Java项目 -->
<!-- war:表示这个项目是一个Web项目 -->
<!-- pom:表示这个项目是父项目 -->
<packaging>jar</packaging>
<properties>
<!-- 项目构建过程中读取源码时使用的字符集 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 当前项目所依赖的jar包 -->
<dependencies>
<!-- 使用 dependency 配置一个具体的依赖 -->
<dependency>
<!-- 在dependency标签内使用具体的坐标依赖我们需要的一个jar包 -->
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.1</version>
<!-- scope标签配置依赖的范围 compile 默认的可以不写-->
<scope>compile</scope>
<!-- 使用 excludes 标签排除不需要的依赖 -->
<exclusions>
<!-- 在 exclude 标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标 这里无需要写version -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Maven 管理父子项目
创建父项目
demo-parent 项目 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.my.study</groupId>
<artifactId>demo-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 当前项目是父项目 打包方式是 pom -->
<packaging>pom</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
创建子项目
子项目 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">
<!-- 当前项目的父项目-->
<parent>
<artifactId>demo-parent</artifactId>
<groupId>com.my.study</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 子项目的 artifactId -->
<artifactId>demo-child</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
此时再看父项目的 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.my.study</groupId>
<artifactId>demo-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 被父项目管理的子项目 -->
<modules>
<module>demo-child</module>
<!-- 这里可以有多个子项目 -->
</modules>
<!-- 当前项目是父项目 打包方式是 pom -->
<packaging>pom</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>
modules 标签是管理子项目的标签。
父项目自定义属性
同一个系统的各个子项目依赖的 jar 包最好使用相同的版本,为了方便版本的管理,我们可以将 jar 的版本号信息维护在父项目中,通过自定义属性来实现,子项目引用父项目中的依赖信息时,可以把版本号去掉,自定义版本号如下:
<properties>
<!-- 通过自定义属性,统一指定 Spring alibaba Cloud的版本 -->
<spring.alibaba.cloud.version>2021.1</spring.alibaba.cloud.version>
</properties>
在需要使用的地方使用 ${} 的形式来引用自定义的属性名,如下:
<!--引入 sentinel 支持-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>${spring.alibaba.cloud.version}</version>
</dependency>
build 标签
build 标签由三个子标签组成,分别是目录结构标签(有好几个标签)、插件管理标签(pluginManagement) 、插件标签(plugins),具体如下:
- 目录结构标签(有好几个标签):用来定义项目的结构,项目中一定会用到的标签。
- 插件管理标签(pluginManagement):管理一些插件,项目中很少用到。
- 插件标签(plugins):管理一些插件,项目中一定会用到的标签。
目录结构标签
- sourceDirectory:程序代码存放目录。
- scriptSourceDirectory:脚本存放目录。
- testSourceDirectory:测试代码存放目录。
- outputDirectory:程序代码编译结果输出目录。
- testOutputDirectory:测试代码编译输出目录。
- resources:资源文件存储目录(后面详细讲解)。
- testResources:测试资源文件存放目录。
- directory:构建结果输出目录。
<build>
<finalName>demo-child</finalName>
<sourceDirectory>//</sourceDirectory>
<scriptSourceDirectory>//</scriptSourceDirectory>
<testSourceDirectory>//</testSourceDirectory>
<outputDirectory>//</outputDirectory>
<testOutputDirectory>//</testOutputDirectory>
</build>
插件管理标签
- maven-antrun-plugin:主要是执行一些 ant 任务,在 Maven 还没诞生的时候 Java 代码主要编译工具是 ant,因此为了要兼容老的 ant 编译,使用 maven-antrun-plugin 就能完成。
- maven-assembly-plugin:是 Maven 中针对打包任务而提供的标准插件,可以实现自定义打包。
- maven-jar-plugin:maven 生命周期 package 阶段的默认打包插件,当不想对该插件进行自定义配置时,就不用在 pom.xml 中主动声明该插件。
- maven-dependency-plugin:是一个依赖管理插件,大部分情况下我们使用它都是和 maven-jar-plugin 配合来使用,将项目的执行 jar 和依赖的 jar 进行分离管理,这样可以减少项目执行 jar 的大小。
- maven-release-plugin:主要作用是在 Maven 项目中执行版本发布流程的插件,它的主要功能是简化项目版本的发布和管理,确保版本号的正确性,并自动处理与版本发布相关的任务。
插件标签
plugin 定义插件的标签,插件也是通过坐标定义的,项目中常用的插件如 maven-deploy-plugin、spring-boot-maven-plugin 插件等,其中 spring-boot-maven-plugin 插件不是 maven 自带的插件,使用 maven 自带的打包插件 maven-jar-plugin 打出来的 jar 包不会把依赖 jar 一起打进去,是一个普通 jar 包,无法使用 java -jar 进行启动,因此 Spring Boot 提供了 spring-boot-maven-plugin 插件来打包。
<plugins>
<!--plugin 表示我是一个插件-->
<plugin>
<!--插件的坐标 groupId artifactId version -->
<!--spring-boot-maven-plugin 打包插件 使用此插件在打Jar包时会引入依赖包-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<!--maven-deploy-plugin 将项目部署到 maven 仓库-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
resources 标签详解
通常情况下,maven 项目中默认资源文件在 src/main/resources 和 src/test/resources 目录下,但是会有一下特殊情况:
- 需要添加 src/main/resources 目录外的的配置文件。
- 只需要 src/main/resources 目录中的部分配置文件。
- 需要对 src/main/resources 中配置文件的变量,进行placeholder进行解析值替换。
resources 标签示例如下:
<build>
<resources>
<resource>
<!--资源文件目录-->
<directory>src/main/resources</directory>
<!--打包时候是否进行变量替换-->
<filtering>false</filtering>
<!--仅某些文件被打包-->
<includes>
<include>application.properties</include>
<!-- **表示任意目录,*.*表示任意文件名和扩展名-->
<include>**/*.*</include>
</includes>
<!--指定哪些文件不被打包-->
<excludes>
<exclude>application.yaml</exclude>
</excludes>
</resource>
</resources>
</build>
resources 中各个标签的含义
- :指定资源目录。
- :指定资源文件目录中,哪些文件被打包。
- :指定资源文件目录中,哪些文件不被打包。
- :是一个 boolean 值,默认值为 false,指定打包时的配置文件中是否进行变量替换。
使用 filtering 完成变量替换
src/main/resources 下 application.properties 文件配置如下:
application.username=${username}
application.password=${password}
在 pom .xml 文件中定义变量如下:
<properties>
<username>mysql</username>
<password>password123</password>
</properties>
对配置文件中变量进行替换,给 标签复制为 true。
<resource>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
</includes>
<filtering>true</filtering>
</resource>
注意:includes 和 excludes 标签同时使用的时候取交集,一般情况下单独使用其中一个即可满足要求。
profile 标签
profile 标签是环境配置标签,通常情况下我们的项目运行有三种环境,开发、测试、生产环境,我们使用 profile 标签可以完成多环境管理,profile 标签多环境配置如下:
<build>
<!-- profile对资源的操作 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 先排除所有环境相关的配置文件 -->
<excludes>
<exclude>application*.yml</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<!--通过开启 filtering -->
<filtering>true</filtering>
<includes>
<include>application.yml</include>
<include>application-${profileActive}.yml</include>
</includes>
</resource>
</resources>
</build>
<!--多环境文件配置-->
<profiles>
<!--开发环境-->
<profile>
<id>dev</id>
<activation>
<!--默认激活-->
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profileActive>dev</profileActive>
</properties>
</profile>
<!--测试环境-->
<profile>
<id>test</id>
<properties>
<profileActive>test</profileActive>
</properties>
</profile>
<!--正式环境-->
<profile>
<id>prod</id>
<properties>
<profileActive>prod</profileActive>
</properties>
</profile>
</profiles>
我们可以在 application.yml 中配置如下:
spring.profiles.active='@profileActive@'
profileActive是我们在 pom.xml 中配置的文件,这样就可以完成不同环境的配置。
Maven 常用命令
- mvn clean:清除 target 目录。
- mvn compile:编译 main 目录。
- mvn test:执行所有的测试方法。
- mvn package:打包命令,打包当前的项目到 target 目录。
- mvn install:打包并且发布到本地仓库。
- mvn install -Dmaven.test.skip=true:只打包不测试(跳过测试)。
如有不正确的地方请各位指出纠正。