文章目录
1. Maven 简介
Maven 是一款为 Java 项目管理构建、依赖管理的工具(软件),使用 Maven 可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
- 依赖管理工具:jar包自动下载、通过依赖坐标自动加载jar包、处理jar包之间复杂依赖关系
- aven 可以管理项目的依赖,包括自动下载所需依赖库、自动下载依赖需要的依赖并且保证版本没有冲突、依赖版本管理等。通过 Maven,我们可以方便地维护项目所依赖的外部库,避免版本冲突和转换错误等,而我们仅仅需要编写配置即可。
- 构建工具:脱离IDE环境之后构建,需要专门的构建工具
- 项目构建是指将源代码、配置文件、资源文件等转化为能够运行或部署的应用程序或库的过程
- Maven 可以管理项目的编译、测试、打包、部署等构建过程。通过实现标准的构建生命周期,Maven 可以确保每一个构建过程都遵循同样的规则和最佳实践。同时,Maven 的插件机制也使得开发者可以对构建过程进行扩展和定制。主动触发构建,只需要简单的命令操作即可。
2. Maven的安装和配置
2.1 安装流程
(图是我之前早配好的maven)
(1)官网地址,点击下载即可
(2)直接解压,放到你想放的地方,目录最好是没有空格没有中文
接下好的文件目录如下:
- bin:含有Maven的运行脚本
- boot:含有plexus-classworlds类加载器框架
- conf:含有Maven的核心配置文件
- lib:含有Maven运行时所需要的Java类库
- LICENSE、NOTICE、README.txt:针对Maven版本,第三方软件等简要介绍
(3)配置环境变量
① 右键此电脑 --> 高级系统设置 --> 高级 --> 环境变量 --> 系统变量部分 --> 新建
变量名:MAVEN_HOME
变量值:你解压好的maven的目录
② 找到path --> 编辑 --> 新建 --> 输入%MAVEN_HOME%\bin
(3) 测试安装结果
win + R
输入 cmd
唤起命令行
输入 mvn -v
2.2 功能配置
(1)配置本地仓库地址
配置文件在你maven目录下的conf中settings.xml
设置本地仓库地址:将你的地址写在<localRewpository></localRepository>
中
如:
(2)配置国内阿里云镜像
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
(3)配置JDK17版本项目构建
<profile>
<id>jdk-17</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>17</jdk>
</activation>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.compilerVersion>17</maven.compiler.compilerVersion>
</properties>
</profile>
java8这样写:
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
(4)idea配置maven
配上你的maven地址、settings.xml、仓库地址,取消勾选
3. 关于MAVEN的一些概念/用法
3.1 Maven工程中的GAVP
Maven工程相对之前的项目,多出一组GAVP属性,gav需要我们在创建项目的时候指定,p有默认值,我们先行了解下这组属性的含义:
Maven 中的 GAVP 是指 GroupId
、ArtifactId
、Version
、Packaging
等四个属性的缩写,其中前三个是必要的,而 Packaging
属性为可选项(例如java就是jar包)。这四个属性主要为每个项目在maven仓库中做一个标识,类似人的姓-名,有了具体标识,方便后期项目之间相互引用依赖等。
GAV遵循一下规则:
(1) GroupID 格式:com.{公司/BU}.业务线.[子业务线],最多 4 级。
说明:{公司/BU} 例如:alibaba/taobao/tmall/aliexpress 等 BU 一级;子业务线可选。
正例:com.taobao.tddl 或 com.alibaba.sourcing.multilang
(2) ArtifactID 格式:产品线名-模块名。语义不重复不遗漏,先到仓库中心去查证一下。
正例:tc-client / uic-api / tair-tool / bookstore
(3) Version版本号格式推荐:主版本号.次版本号.修订号
- 主版本号:当做了不兼容的 API 修改,或者增加了能改变产品方向的新功能。
- 次版本号:当做了向下兼容的功能性新增(新增类、接口等)。
- 修订号:修复 bug,没有修改方法签名的功能加强,保持 API 兼容性。
例如: 初始→1.0.0 修改bug → 1.0.1 功能调整 → 1.1.1等
Packaging定义规则:
- 指示将项目打包为什么类型的文件,idea根据packaging值,识别maven项目类型!
- packaging 属性为 jar(默认值),代表普通的Java工程,打包以后是.jar结尾的文件。
- packaging 属性为 war,代表Java的web工程,打包以后.war结尾的文件。
- packaging 属性为 pom,代表不会打包,用来做继承的父工程。
3.2 Maven工程项目结构
|-- pom.xml # Maven 项目管理文件
|-- src
|-- main # 项目主要代码
| |-- java # Java 源代码目录
| | `-- com/example/myapp # 开发者代码主目录
| | |-- controller # 存放 Controller 层代码的目录
| | |-- service # 存放 Service 层代码的目录
| | |-- dao # 存放 DAO 层代码的目录
| | `-- model # 存放数据模型的目录
| |-- resources # 资源目录,存放配置文件、静态资源等
| | |-- log4j.properties # 日志配置文件
| | |-- spring-mybatis.xml # Spring Mybatis 配置文件
| | `-- static # 存放静态资源的目录
| | |-- css # 存放 CSS 文件的目录
| | |-- js # 存放 JavaScript 文件的目录
| | `-- images # 存放图片资源的目录
| `-- webapp # 存放 WEB 相关配置和资源
| |-- WEB-INF # 存放 WEB 应用配置文件
| | |-- web.xml # Web 应用的部署描述文件
| | `-- classes # 存放编译后的 class 文件
| `-- index.html # Web 应用入口页面
`-- test # 项目测试代码
|-- java # 单元测试目录
`-- resources # 测试资源目录
其中webapp目录是javaweb、javase项目并且是非前后端分离项目用到的,放置前端文件的目录,要求打包方式是war包,并且在File --> Project Structure
中配置生成,或者IDEA安装JBLJavaToWeb框架去生成,这里不多赘述。
3.3 构建概念和构建过程
项目构建: 是指将源代码、依赖库和资源文件转成可执行/可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤;提高开发效率,使得开发人员专注程序开发和维护,不必关心构建细节;可汇合多人代码,自动化构建和部署,大大降低项目出错风险。常见工具有:maven、gradle、ant。
构建流程:清理 --> 编译 --> 测试 --> 报告 --> 打包 --> 部署
用命令的方式进行项目构建:
命令 | 描述 |
---|---|
mvn compile | 编译项目,生成target文件 |
mvn package | 打包项目,生成jar或war文件 |
mvn clean | 清理编译或打包后的项目结构 |
mvn install | 打包后上传到maven本地仓库 |
mvn deploy | 只打包,上传到maven私服仓库 |
mvn site | 生成站点 |
mvn test | 执行测试源码 |
war包打包插件和jdk不匹配时,可以在pom.xml中添加如下代码:
<build>
<!-- jdk17 和 war包版本插件不匹配 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
IDEA中的项目构建
打包(package)和安装(install)的区别是:打包是将工程打成jar或war文件,保存在target目录下;安装是将当前工程所生成的jar或war文件,安装到本地仓库,会按照坐标保存到指定位置
3.4 构建插件、命令、生命周期命令之间关系
构建生命周期:一组固定构建命令的有序集合,触发周期后的命令,会自动触发周期前的命令
例如打包:mvn clean package
,其中包括两个构建生命周期
- 清理周期:clean
- 默认周期:compile - test - package
全周期:
compile - test - package - install - deploy
关系:
- 周期→包含若干命令→包含若干插件
- 使用周期命令构建,简化构建过程!
- 最终进行构建的是插件
3.5 依赖管理概念以及配置解读
maven依赖管理的概念:
- Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题,使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中,避免出现版本冲突和依赖缺失等问题。
- 我们通过定义 POM 文件,Maven 能够自动解析项目的依赖关系,并通过 Maven仓库 自动下载和管理依赖,从而避免了手动下载和管理依赖的繁琐工作和可能引发的版本冲突问题。
- Maven 的依赖管理是 Maven 软件的一个核心功能之一,使得软件包依赖的管理和使用更加智能和方便,简化了开发过程中的工作,并提高了软件质量和可维护性。
Pom文件解读:
<!-- 模型版本 -->
<modelVersion>4.0.0</modelVersion>
<!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
<groupId>com.companyname.project-group</groupId>
<!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
<artifactId>project</artifactId>
<!-- 版本号 -->
<version>1.0.0</version>
<!--打包方式
默认:jar
jar指的是普通的java项目打包方式! 项目打成jar包!
war指的是web项目打包方式!项目打成war包!
pom不会讲项目打包!这个项目作为父工程,被其他工程聚合或者继承!后面会讲解两个概念
-->
<packaging>jar/pom/war</packaging>
引入依赖:maven仓库网站
<dependencies>
<!-- 引入具体的依赖包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<!-- 依赖范围 -->
<scope>runtime</scope>
</dependency>
</dependencies>
版本号声明(本质类似于变量):依赖版本统一提取和维护:
<!--声明版本-->
<properties>
<!--命名随便,内部制定版本号即可!-->
<junit.version>4.12</junit.version>
<!-- 也可以通过 maven规定的固定的key,配置maven的参数!如下配置编码格式!-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!--引用properties声明版本 -->
<version>${junit.version}</version>
</dependency>
</dependencies>
3.6 依赖范围
通过设置坐标的依赖范围(scope),可以设置 对应jar包的作用范围:编译环境、测试环境、运行环境
依赖范围 | 描述 |
---|---|
compile | 编译依赖范围,scope 元素的缺省值。使用此依赖范围的 Maven 依赖,对于三种 classpath 均有效,即该 Maven 依赖在上述三种 classpath 均会被引入。例如,log4j 在编译、测试、运行过程都是必须的。 |
test | 测试依赖范围。使用此依赖范围的 Maven 依赖,只对测试 classpath 有效。例如,Junit 依赖只有在测试阶段才需要。 |
provided | 已提供依赖范围。使用此依赖范围的 Maven 依赖,只对编译 classpath 和测试 classpath 有效。例如,servlet-api 依赖对于编译、测试阶段而言是需要的,但是运行阶段,由于外部容器已经提供,故不需要 Maven 重复引入该依赖。 |
runtime | 运行时依赖范围。使用此依赖范围的 Maven 依赖,只对测试 classpath、运行 classpath 有效。例如,JDBC 驱动实现依赖,其在编译时只需 JDK 提供的 JDBC 接口即可,只有测试、运行阶段才需要实现了 JDBC 接口的驱动。 |
system | 系统依赖范围,其效果与 provided 的依赖范围一致。其用于添加非 Maven 仓库的本地依赖,通过依赖元素 dependency 中的 systemPath 元素指定本地依赖的路径。鉴于使用其会导致项目的可移植性降低,一般不推荐使用。 |
import | 导入依赖范围,该依赖范围只能与 dependencyManagement 元素配合使用,其功能是将目标 pom.xml 文件中 dependencyManagement 的配置导入合并到当前 pom.xml 的 dependencyManagement 中。 |
3.7 依赖下载失败的解决方案
- 网路故障/仓库服务器宕机:检查网络连接和Maven仓库服务器状态
- 依赖中版本号错误/依赖项没有正确定义:去官网查正确的定义,确保gva三项匹配,以及依赖的前置依赖匹配
- 本地Maven仓库被污染/损坏:清除本地仓库缓存(
lastupdated
缓存文件),直接删除本地仓库内该依赖对应版本的文件夹即可
3.8 Maven工程Build构建配置
项目构建: 是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程,在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。
默认情况下,构建不需要额外配置,都有对应的缺省配置。当然了,我们也可以在pom.xml定制一些配置,来修改默认构建的行为和产物,例如:
- 指定构建打包文件的名称,非默认名称
- 制定构建打包时,指定包含文件格式和排除文件
- 打包插件版本过低,配置更高版本插件
构建配置是在pom.xml / build标签中指定:
指定打包命名
<!-- 默认的打包名称:artifactid+verson.打包方式 -->
<build>
<finalName>定义打包名称</finalName>
</build>
指定打包文件
如果在java文件夹中添加java类,会自动打包编译到classes文件夹下!
但是在java文件夹中添加xml文件,默认不会被打包!
默认情况下,按照maven工程结构放置的文件会默认被编译和打包!
除此之外、我们可以使用resources标签,指定要打包资源的文件夹要把哪些静态资源打包到 classes根目录下!
应用场景:mybatis中有时会将用于编写SQL语句的映射文件和mapper接口都写在src/main/java下的某个包中,此时映射文件就不会被打包,如何解决
<build>
<!--设置要打包的资源位置-->
<resources>
<resource>
<!--设置资源所在目录-->
<directory>src/main/java</directory>
<includes>
<!--设置包含的资源类型-->
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
配置依赖插件
dependencies标签下引入开发需要的jar包,我们可以在build/plugins/plugin标签引入插件
常用的插件:修改jdk版本、tomcat插件、mybatis分页插件、mybatis逆向工程插件等等
<build>
<plugins>
<!-- java编译插件,配jdk的编译版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8090</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
3.9 依赖传递的特性/原则
依赖传递中止方法:
- 非compile范围进行以来传递
- 使用optional配置中止传递
<optional>true</optional>
- 依赖冲突
解决依赖冲突(如何选择重复依赖)方式:
- 自动选择原则
- 短路优先原则(第一原则):同一依赖找最短路径上的依赖
- A—>B—>C—>D—>E—>X(version 0.0.1)
- A—>F—>X(version 0.0.2)
- 则A依赖于X(version 0.0.2)
- 依赖路径长度相同情况下,则“先声明优先”(第二原则)
- A—>E—>X(version 0.0.1)
- A—>F—>X(version 0.0.2)
- 则A依赖于X(version 0.0.1)
- 短路优先原则(第一原则):同一依赖找最短路径上的依赖
- 手动排除
<dependency>
<groupId>com.atguigu.maven</groupId>
<artifactId>pro01-maven-java</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
<!-- 使用excludes标签配置依赖的排除 -->
<exclusions>
<!-- 在exclude标签中配置一个具体的排除 -->
<exclusion>
<!-- 指定要排除的依赖的坐标(不需要写version) -->
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
4. Maven工程继承和聚合关系
4.1 Maven工程继承关系
继承概念: Maven 继承是指在 Maven 的项目中,让一个项目从另一个项目中继承配置信息的机制。继承可以让我们在多个项目中共享同一配置信息,简化项目的管理和维护工作。
继承作用: 在父工程中统一管理项目中的依赖信息。
它的背景是:
- 对一个比较大型的项目进行了模块拆分。
- 一个 project 下面,创建了很多个 module。
- 每一个 module 都需要配置自己的依赖信息。
它背后的需求是:
- 在每一个 module 中各自维护各自的依赖信息很容易发生出入,不易统一管理。
- 使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一。
- 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。
4.2 继承语法
父工程
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
<packaging>pom</packaging>
子工程
<!-- 使用parent标签指定当前工程的父工程 -->
<parent>
<!-- 父工程的坐标 -->
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- 子工程的坐标 -->
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
<!-- <groupId>com.atguigu.maven</groupId> -->
<artifactId>pro04-maven-module</artifactId>
<!-- <version>1.0-SNAPSHOT</version> -->
4.3 父工程依赖统一管理
父工程声明版本
<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有真正被引入到工程 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.0.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>6.0.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>6.0.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.0.10</version>
</dependency>
</dependencies>
</dependencyManagement>
子工程引用版本
<!-- 子工程引用父工程中的依赖信息时,可以把版本号去掉。 -->
<!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程决定。 -->
<!-- 具体来说是由父工程的dependencyManagement来决定。 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
</dependencies>
4.4 Maven工程聚合关系
聚合概念: Maven 聚合是指将多个项目组织到一个父级项目中,以便一起构建和管理的机制。聚合可以帮助我们更好地管理一组相关的子项目,同时简化它们的构建和部署过程。
聚合作用:
- 管理多个子项目:通过聚合,可以将多个子项目组织在一起,方便管理和维护。
- 构建和发布一组相关的项目:通过聚合,可以在一个命令中构建和发布多个相关的项目,简化了部署和维护工作。
- 优化构建顺序:通过聚合,可以对多个项目进行顺序控制,避免出现构建依赖混乱导致构建失败的情况。
- 统一管理依赖项:通过聚合,可以在父项目中管理公共依赖项和插件,避免重复定义。
聚合语法:
父项目中包含的子项目列表。
<project>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
<modules>
<module>child-project1</module>
<module>child-project2</module>
</modules>
</project>