POM
- Project Object Model: 项目对象模型.
- 将Java工程的相关信息封装为对象作为便于操作和管理的模型Maven工程 的核心配置, 可以说学习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"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-01</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> <scope>provided</scope> </dependency> </dependencies> </project>
- modelVersion: 模型版本
- 坐标: groupId, artifactId, version
- name: 项目名称
- dependencies: 依赖
约定的目录结构
- 现在JavaEE开发领域普遍认同一个观点: 约定>配置>编码, 意思就是能用配置解 决的问题就不编码, 能基于约定的就不进行配置.
- 而Maven正是因为指定了特定文件保存的目录才能够对我们的Java工程进行自动化构建.
坐标
- 几何中的坐标
- 二维平面: x, y确定一个点
- 三维空间: x, y, z确定一个点.
- Maven坐标
- 使用如下三个向量在maven仓库中唯一确定一个maven工程.
- groupId: 公司或组织的域名倒序+当前项目名.
- artifactId: 当前项目的模块名称
- version: 当前模块的版本
<groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version>
- 使用如下三个向量在maven仓库中唯一确定一个maven工程.
- 如何通过坐标到仓库中找jar包
- 将gav三个向量连起来
- org.projectlombok + lombok + 1.18.8
- 将连起来的字符串作为目录结构到仓库中查找
- orgprojectlomboklombok1.18.8lombok-1.18.8.jar
- 将gav三个向量连起来
- 在pom.xml的dependencies标签中填写坐标, 然后重新编译项目, 就会从中央仓库(镜像)中下载jar包.
依赖管理
- 基本概念
- 当A jar包需要用到B jar包中的类时, 我们就说A对B有依赖.
- 当前工程回到本地仓库中根据坐标查找它所依赖的jar包, 配置的基本形式是使用dependency标签指定目标jar包的坐标.
<dependency> <groupId>com.example</groupId> <artifactId>HelloWorld</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> </dependency>
- 直接依赖和间接依赖
- 如果A依赖B, B依赖C, 那么A→B和B→C都是直接依赖, 而 A→C 是间接依赖.
- 依赖的范围
- 在dependency标签下的scope标签中管理.
- compile
- main目录下的Java代码可以访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时要放在WEB-INF的lib目录下
- 是默认值.
- 例如: 上面对HelloWorld的依赖, 主程序, 测试程序和服务器运行时都需要用到.
- test
- main目录下的Java代码不能访问这个范围的依赖.
- test目录下的Java代码可以访问这个范围的依赖.
- 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下.
- 例如: 对junit的依赖, 仅仅是测试程序部分需要.
- provided
- main目录下的Java代码可以访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时不会放在WEB-INF的lib目录下
- 例如: servlet-api在服务器上运行时, Servlet容器会提供相关API, 所以部署的时候不需要.
- runtime
- main目录下的Java代码不能访问这个范围的依赖
- test目录下的Java代码可以访问这个范围的依赖
- 部署到Tomcat服务器上运行时会放在WEB-INF的lib目录下.
- 例如: JDBC驱动, 只有在测试运行和在服务器运行的时候才决定使用什么样的数据库连接.
- 传递的依赖性
- 只有compile具有传递性
- 依赖的原则: 要解决jar包冲突
- 路径最短者优先
- 路径长度相同则先声明者优先.
- 声明的先后顺序就是在pom.xml中dependency的顺序.
- 路径最短者优先
- 依赖的排除
- 有的时候为了确保程序正确可以将有可能重复的间接依赖排除.
- dependency标签中的<exclusion>标签内写坐标.
<dependency> <groupId>org.springframework</groupId> <artifactId>spring‐core</artifactId> <exclusions> <exclusion> <groupId>commons‐logging</groupId> <artifactId>commons‐logging</artifactId> </exclusion> </exclusions> </dependency>
- 统一管理目标的jar包的版本
- 以对Spring的jar包依赖为例: Spring的每一个版本中都包含spring-core, spring-context等jar包.
- 如果要对这些jar包的版本统一升级, 难道要一个一个修改版本?
- 可以在<properties>下自定义标签设置统一的配置方式
<properties> <spring.version>5.0.8.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> </dependencies>
仓库
- 分类
- 本地仓库: 当前本机电脑上的所有Maven工程服务.
- 远程仓库
- 私服: 架设在当前局域网下, 为当前局域网范围内的所有maven工程服务.
- 中央仓库: 架设在Internet上, 为全世界所有Maven工程服务.
- 中央仓库的镜像: 架设在各个大洲,为中央仓库分担流量。减轻中央仓 库的压力,同时更快的响应用户请求.
- 私服: 架设在当前局域网下, 为当前局域网范围内的所有maven工程服务.
- 仓库中的文件
- maven的插件
- 我们自己开发的项目的模块
- 第三方框架或工具的jar包.
- 不管是什么样的jar包, 在仓库中都是按照坐标生成目录结构, 所以可以通过统一的方式查询或依赖.
- maven的插件
生命周期
- 什么是生命周期
- maven生命周期定义了各个构建环节的执行顺序, 有了这个清单, maven就可以自动化的执行构建命令了.
- maven有三套互相独立的声明周期, 可以仅仅调用clean来清理工作目录, 仅 仅调用site来生成站点, 当然你也可以直接运行mvn clean install site运行所 有这三套生命周期.
- Clean Lifecycle
- Default Lifecycle
- Site Lifecycle.
- 每套生命周期都由一组阶段(Phase)组成, 我们平时在命令行输入的命令总会 对应于一个特定的阶段.
- Clean生命周期
- pre-clean执行一些需要在clean之前完成的工作.
- clean移除所有上一次构建生成的文件
- post-clean执行一些需要在clean之后立刻完成的工作
- Site生命周期
- pre-site执行一些需要在生成站点文档之前完成的工作
- site生成项目的站点文档
- post-site执行一些需要在生成站点文档之后完成的工作, 并且为部署做准备.
- site-deploy将生成的站点文档部署到特定的服务器上
- Default生命周期
- Default生命周期是Maven生命周期中最重要的一个, 绝大部分工作都发生在这个生命周期中.
- 生命周期与自动化构建
- 运行任何一个阶段的时候, 它前面的所有阶段都会被运行.
- 例如: 运行mvn install的时候, 代码会被编译, 测试, 打包. 这就是Maven为什么能够自动执行构建过程的各个环节的原因.
- 此外, Maven的插件机制是完全依赖 Maven 的生命周期的, 因此理解生命周期至关重要.
插件和目标
- Maven的核心仅仅定义了抽象的生命周期, 具体的任务都是交由插件完成的.
- 每个插件都能实现多个功能, 每个功能就是一个插件目标.
- Maven的生命周期与插件目标相互绑定, 以完成某个具体的构建任务.
- 举例, compile就是插件maven-compiler-plugin的一个功能, pre-clean是插件 maven-clean-plugin的一个目标
继承
- 为什么要继承?
- 由于非compile范围的依赖信息是不能在"依赖链"中传递的, 所以有需要的工程只能单独配置.
- 但这样会造成大量的冗余, 所以要使用继承.
- 创建父工程
- 只需用IDEA创建一个普通的maven工程.
- 这里建议把其src删掉, 因为父工程内只做依赖管理.
- 创建子工程
- 在上一步创建的工程中New Module, 创建子工程.
- 当一个普通maven工程有子工程后, 它的打包方式会自动变为pom,
- 而子工程会自动引入父工程, 如
<parent> <artifactId>spring-02</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent>
- 而子工程会自动引入父工程, 如
- 在父工程中管理依赖
- 在父工程中, 用<dependencyManagement>把<dependencies>括起来.
<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
- 子项目现在可以删除范围和版本号, 但是<groupId>和<artifactId>不能删.
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency>
- 若子项目想用其他的版本, 则可以加上<version>
- 在父工程中, 用<dependencyManagement>把<dependencies>括起来.
聚合
- 为什么要使用聚合?
- 将多个工程拆分为模块后, 需按顺序逐个安装到仓库后依赖才能生效, 修改源码后也需要逐个手动clean, 而使用了聚合后可以批量安装, 清理操作了.
- 配置聚合
- 在总的聚合工程中使用<modules></modules>标签组合, 指定模块工程的相对路径即可.
<modules> <module>spring-02-child1</module> </modules>
- 在总的聚合工程中使用<modules></modules>标签组合, 指定模块工程的相对路径即可.