Maven
1.什么是Maven
官方网站 https://maven.apache.org/
Maven是一款服务于Java平台的自动化构建工具,它可以帮助我们更方便的对项目进行构建、管理项目jar包
,包括: bulid 项目,切换 jar 版本,添加 jar, 删除 jar 包等
1.1 Maven下载和安装
- 第 1 种方式: 直接使用 idea 自带的 Maven
- 第 2 种方式: 自己下载 Maven 软件, 安装、配置并使用.
- 下载地址 https://archive.apache.org/dist/maven/maven-3/
安装步骤
- 直接解 maven 安装到指定目录
- 目录结构说明
- maven 使用需要依赖 jdk ,因此事先要保证安装了 jdk1.8 以上
- 配置环境变量 MAVEN_HOME
- 配置环境变量 PATH, 增加 Maven 的路径, (如果有多个 Maven 的 Path, 可以上移, 提高优先级)
- 测试是否安装 maven 成功.
1.2 Maven 工作原理图
- 在 maven 项目的 pom.xml, 可以配置项目依赖的 jar(指定坐标即可)
- maven 根据配置, 到中央仓库/私服 去获取 jar,下载到本地仓库
- maven 项目, 会引用本地仓库的 jar ,完成项目开发
- 在 maven 项目构建生命周期中,每个阶段的执行都有相应的插件完成
- 各个插件执行过程中,会附带输出内容,比如 jar/war/xml/源码
- 程序员可以使用 maven 默认的插件,也可以自定义插件,完成定制任务.
Maven 项目统一的开发结构分析:
2.Maven 相关概念
2.1仓库:存储项目需要的 jar 包
- 几乎所有的 jar 包都保存在中央仓库 . 地址: https://mvnrepository.com/
- 本地仓库:在使用 maven 时,会将需要的 jar 下载到本地,保存在指定目录下,称为本地仓库(如图)
- 私服: 开发团队搭建的存储资源的仓库,可以个性化仓库(比如只供团队使用的 jar), 同时提升下载速度
- 我们个人开发时,可以直接从中央仓库下,如果想提升下载速度,可以设置镜像仓库
2.2 坐标
作用: 资源的唯一标识,定位 Maven 仓库中资源的位置
坐标构成
- groupld(组织 id): 定义当前 Maven 项目隶属组织名称(例如∶com.spring)
- artifactId(项目 ID): 定义当前 Maven 项目名称
- version(版本号): 定义当前项目版本号
- 如何获取 jar 坐标
- 比如 mysql jar
3.Maven构建指令
3.1 完成编译
- 编译指令
mvn compile
mvn compile
- 编程成功,会自动创建 target 目录,并生成对应的.class 文件(如图)
- 细节说明: 第一次速度慢,需要下载相关 jar,后面就快了.
3.2完成测试
- 测试指令
mvn test
mvn test
- 测试指令执行完毕,会生成 Test 源文件的 class , 还会输出测试结果
- 细节说明: 第一次速度慢,需要完成一些初始化工作,后面就快了
3.3 完成打包
- 打包指令
mvn package
mvn package
- 打包后,在 target 目录生成对应的 打包文件 jar
3.4 完成安装
- 执行 install 指令,能完成 maven 项目的安装,会把打包得到的 jar, 提交到本地仓库
- 当把 maven-project01-1.0-SNAPSHOT.jar 提交到本地仓库后,该 jar 也可以被其他 maven 项目使用了,非常方便
3.5完成清理
执行如下指令,完成 maven 项目的清理,会清除生成的 target 目录
shellmvn clean
mvn clean
3.6小结 Maven 构建指令
● 说明: Maven 构建命令使用 mvn 开头,后面添加功能参数,可以一次执行多个命令,使 用空格分隔
mvn compile #编译
mvn clean #清理
mvn test #测试
mvn package #打包
mvn install #安装
mvn compile #编译
mvn clean #清理
mvn test #测试
mvn package #打包
mvn install #安装
4.IDEA创建 Maven Web 工程
- 需求说明/图解
创建成功的 maven web 项目结构
创建的 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>
<!--
1. 前面三个 groupId , artifactid 和 version 就是该 maven 项目坐标
2. package 是打包方式,默认是 jar , 这里是 war(因为这是 web 项目)
-->
<groupId>com.llp</groupId>
<artifactId>maven-javaWeb</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>maven-javaWeb Maven Webapp</name>
<url>http://www.example.com</url>
<!--maven项目的属性,根据实际情况可以修改-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--创建maven项目默认引入的jar-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--默认引入的 maven 插件, 前面说过 mvn 的各种指令 compile/install/test 等都是由插件完成的 -->
<build>
<finalName>maven-javaWeb</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
<?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>
<!--
1. 前面三个 groupId , artifactid 和 version 就是该 maven 项目坐标
2. package 是打包方式,默认是 jar , 这里是 war(因为这是 web 项目)
-->
<groupId>com.llp</groupId>
<artifactId>maven-javaWeb</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>maven-javaWeb Maven Webapp</name>
<url>http://www.example.com</url>
<!--maven项目的属性,根据实际情况可以修改-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--创建maven项目默认引入的jar-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--默认引入的 maven 插件, 前面说过 mvn 的各种指令 compile/install/test 等都是由插件完成的 -->
<build>
<finalName>maven-javaWeb</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
- 配置 Tomcat 服务器&运行
- 为 maven web 项目配置 tomcat
5.Maven依赖管理
5.1依赖配置
一句话: 依赖指当前项目运行需要的 jar,一个项目可以设置多个依赖
● 依赖的举例
<!--
1. 这里就是引入项目需要的 jar 包, 类似传统的 import jar 的作用
2. 在 dependencies 标签内,可以指定多个需要依赖的 jar/导入的 jar
3. 引入的 jar 包需要一个完整的 jar 包坐标,从 mvn 仓库查询即可得到-->
<dependencies>
<!-- 引入的一个具体的依赖 jar, 包括一个完整的依赖坐标 -->
<dependency>
<!-- 依赖的 gruopid: 组织名 -->
<groupId>junit</groupId>
<!-- 依赖的项目名 -->
<artifactId>junit</artifactId>
<!-- 依赖的版本 -->
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--
1. 这里就是引入项目需要的 jar 包, 类似传统的 import jar 的作用
2. 在 dependencies 标签内,可以指定多个需要依赖的 jar/导入的 jar
3. 引入的 jar 包需要一个完整的 jar 包坐标,从 mvn 仓库查询即可得到-->
<dependencies>
<!-- 引入的一个具体的依赖 jar, 包括一个完整的依赖坐标 -->
<dependency>
<!-- 依赖的 gruopid: 组织名 -->
<groupId>junit</groupId>
<!-- 依赖的项目名 -->
<artifactId>junit</artifactId>
<!-- 依赖的版本 -->
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
5.2依赖传递
直接依赖: 在当前项目中通过依赖配置建立的依赖关系
比如,在项目的pom.xml文件中,引入mysql8.0.27,这时我们就说项目直接依赖了mysql8.0.27
<!--引入mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!--引入mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
5.3间接依赖
间接依赖: 当前项目直接依赖资源(比如 m1), 而 m1 又依赖资源(m2),我们就说 当前项目间接依赖资源(m2)
比如,项目A引入了一个mysql8.0.27的jar,而项目B有引入了A项目的jar,这样就形成了间接依赖
5.4依赖冲突
路径优先
- 路径优先∶当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高
- 示意图说明:
- 项目 A 依赖情况
- 如果 1 度资源有 junit 4.1 , 而 2 度资源有 junit4.2
- 根据路径优先原则, 项目 A 生效的是 junit4.1
声明优先
- 声明优先∶当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
- 示意图说明:
特殊优先
- 特殊优先∶当同级配置了相同资源的不同版本,后配置的覆盖先配置的(要尽量避免这种没有意义的冲突)
5.5可选依赖
可选依赖:可选依赖指对外隐藏当前所依赖的资源 - 不透明
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<!--
optional:默认是false,表示不隐藏
optional:设置为true,表示隐藏,其他模块就没办法使用
-->
<optional>true</optional>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<!--
optional:默认是false,表示不隐藏
optional:设置为true,表示隐藏,其他模块就没办法使用
-->
<optional>true</optional>
<scope>test</scope>
</dependency>
5.6 排除依赖
一句话: 排除依赖指主动断开依赖的资源, 被排除的资源无需指定版本- 不需要
<dependencies>
<dependency>
<groupId>com.llp</groupId>
<artifactId>maven-project-2</artifactId>
<version>1.0-SNAPSHOT</version>
<!--
1.指定要排除的依赖
2.可以排除多个,在exclusions下添加多个exclusion即可
-->
<exclusions>
<exclusion>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.llp</groupId>
<artifactId>maven-project-2</artifactId>
<version>1.0-SNAPSHOT</version>
<!--
1.指定要排除的依赖
2.可以排除多个,在exclusions下添加多个exclusion即可
-->
<exclusions>
<exclusion>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
5.7可选依赖和排除依赖区别
一句话: 隐藏依赖是不让其他项目来引用(我不给), 排除依赖是主动不要引入的某个资源(我不要)
5.8依赖范围
一句话: 依赖的 jar 默认情况可以在任何地方使用, 通过 scope 标签设定其作用范围
● 作用范围说明
- 主程序范围有效(src/main 文件夹范围内)
- 测试程序范围有效(src/test 文件夹范围内)
- 是否参与打包(package 指令范围内)
- compile(默认,在主程序、测试代码、打包都有效)
● 作用范围一览图
- 某个引入的 jar 包作用范围是程序员根据,业务的实际需要来设置的,不要认为是固定的。
- 比如 log4j jar 包,在主程序,测试代码,打包都是需要的, 因此作用范围应当设置为complie
- junit 只是测试代码需要,因此作用范围设置为 test 合适,但是如果程序员认为在主程序和打包就是要 junit, 仍然可以设置为默认 compile
- 比如 servlet-api 是 tomcat 自己带的,当把程序打包放到生产环境时,用生产环境tomcat 的 servlet-api 即可,所以设置为 provided 合适,这样就放在 servlet-api 版本冲突.
- 比如 jdbc, 是第三方的 jar , 打包放在生产环境,就应当在自己的包提供 jdbc 驱动包,否则程序会因为少驱动包,运行失败
6.Maven 项目构建生命周期
一句话: Maven 构建生命周期描述的是一次构建过程经历了多少个事件
6.1生命周期的 3 大阶段
- clean∶清理工作
- default∶核心工作,例如编译,测试,打包,部署等
- site∶产生报告,发布站点等
6.2 生命周期是分阶段执行的
一句话: 项目构建生命周期分很多阶段,并不是每次都完整执行,而是根据用户的要求 来执行的【比如你执行 compile, 那么就执行到 complie 这个阶段,如果你执行 install, 则会 执行 compile->test->package->install】
7.maven 插件
7.1介绍
- 插件与生命周期内的某个阶段绑定,在执行到对应生命周期时, 由对应插件来完成任务/功能.
- maven 插件很多,先看一张图:
- 通过插件可以自定义其他功能
7.2 文档
文档: http://maven.apache.org/plugins/index.html
7.3自定义插件-应用实例
需求: 在 pom.xml 加入自定义插件,能够在对 maven_D 项目 打包时,能输出主程序和测试程序的源码
● 完成步骤
- 当前 package 只会得到项目的 jar
- 修改 D:\java_projects\maven_D\pom.xml, 加入 maven 插件 并配置(注意: 加入自定义插件后,可能会爆红,重启项目即可.)
<!-- 在build时, 自定义插件 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<goals>
<!-- 对主程序输出源码打包 -->
<goal>jar</goal>
<!-- 对测试程序输出源码打包 -->
<goal>test-jar</goal>
</goals>
<!-- 指定执行阶段 -->
<phase>generate-test-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- 在build时, 自定义插件 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<goals>
<!-- 对主程序输出源码打包 -->
<goal>jar</goal>
<!-- 对测试程序输出源码打包 -->
<goal>test-jar</goal>
</goals>
<!-- 指定执行阶段 -->
<phase>generate-test-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
- 观察一下 maven 项目管理器
- 再次执行 maven-D 的 intall 操作, 会得到两个新的 jar ,分别包含了主程序和测试程序的源码。(测试时,需要保证 src/main/... 和 src/test/... 两个目录下有 java 源代码,否则不会生成源码 jar)
7.4maven 插件-maven 构建生命周期关系图
- 在 maven 项目构建生命周期中,每个阶段的执行都有相应的插件完成
- 各个插件执行过程中,会附带输出内容,比如 jar/war/xml/源码
- 程序员可以使用 maven 默认的插件,也可以自定义插件,完成定制任务.
- 自定义插件引入成功, 是可以看到