1 Maven简介
1.1 传统项目管理状态的局限
- jar包不统一,jar包不兼容导致项目问题
- 工程升级维护过程操作繁琐
1.2 Maven是什么
Maven的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型POM(Project Object Model:项目对象模型)
Maven是由java语言开发,它管理的东西以面向对象的形式设计,将一个项目看成一个对象,这个对象就叫做POM.
1.3 Maven的作用
- 项目构建:提供标准的、跨平台的自动化项目构建方式。
- 依赖管理:方便快捷的管理项目依赖的资源(jar包),避免资源间的版本冲突问题。
- 统一开发结构:提供标准、统一的项目结构。
2 下载与安装
2.1 Maven下载
官网:https://maven.apache.org/
下载地址:https://maven.apache.org/download.cgi
2.2 Maven安装
解压:
Maven属于绿色版软件,解压即安装
环境变量配置:
- 依赖Java,需要配置JAVA_HOME
- 设置MAVEN自身的运行环境,需要配置MAVEN_HOME
测试环境配置结果:
MVN命令
3 Maven基础概念
3.1 仓库
用于存储资源,包含各种jar包。
仓库分类
- 本地仓库:自己电脑上存储资源的仓库,连接远程仓库获取资源。
- 远程仓库:非本机电脑上的仓库,为本地仓库提供资源。
1. 中央仓库:Maven团队维护,存储所有资源的仓库。
2. 私服:部门/公司范围内存储资源的仓库,从中央仓库获取资源。
私服的作用:
- 保存具有版权的资源,包含购买或自主研发的jar(中央仓库中的jar都是幵源的,不能存储具有版权的资源)。
- 一定范围内共享资源,仅对内部幵放,不对外共享。
3.2 坐标
Maven中的坐标用于描述仓库中资源的位置。
中央仓库地址:https://mvnrepository.com/
Maven坐标主要组成
- groupld:定义当前Maven项目隶属组织名称(通常是域名反写,例如:org.mybatis) 。
- artifactld:定义当前Maven项目名称(通常是模块名称,例如CRM、SMS)。
- version:定义当前项目版本号 。
Maven坐标的作用
使用唯一标识,唯一性定位资源位置,通过该标识可以将资源的识别与下载工作交由机器完成。
3.3 仓库配置
本地仓库配置
Maven启动后,会自动保存下载的资源到本地仓库。
- 默认位置:
<localRepository>$(user.home)/.m2/repository</localRepository>
当前目录位置为登录用户名所在目录下的.m2文件夹中。可通过替换<localRepository>
标签中的地址,重新自定义本地仓库位置。
- 自定义位置:
<localRepository>D:\maven\repository</localRepository>
当前目录位置为 D:\maven\repository文件夹中。
远程仓库配置
Maven默认连接的仓库位置
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2 </url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
Maven默认连接的是位于国外的服务器,下载速度比较慢,可用国内的阿里云镜像仓库进行替换。
镜像仓库配置
在settting文件中配置阿里云镜像仓库。
<mirrors>
<!--配置具体的仓库的下载镜像-->
<mirror>
<!--此镜像的唯一标识符,用来区分不同的mirror元素-->
<id>nexus-aliyun</id>
<!--对哪种仓库进行镜像,简单说就是替代哪个仓库-->
<mirrorOf>central</mirrorOf>
<!--镜像名称-->
<name>Nexus aliyun</name>
<!--镜像URL -->
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
全局setting与用户setting区别
- 全局settting定义了当前计算机中Maven的公共配置。
- 用户settting定义了当前用户的配置。
4 第一个Maven项目(手工制作)
4.1 Maven工程目录结构
- 按照以下目录结构手动创建各文件夹,java文件放在main/java目录下,测试文件放在test/java目录下。
- 在src同层的目录下创建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.0http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>project-java</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
4.2 构建命令
Maven构建命令使用mvn开头,后面添加功能参数,可以一次执行多个命令,使用空格分隔。
在pom文件所在目录下执行以下命令,即cd project/java-project目录下。
- mvn compile
编译项目。此时会进行两个操作:
一、下载插件。在本地仓库中下载执行compile功能所需的插件。
二、编译项目。target目录下就是编译完成的内容。
- mvn clean
清除编译完成的目录target - mvn test
测试,生成的测试报告位于target/surefire-reports目录下。
- mvn package
打包源程序。过程中包含compile和test操作。
- mvn install
将打包好的jar包安装到本地仓库。注意jar包的存放位置:groupId+artifactId+version
4.3 插件创建工程
Maven工程目录除了通过自己手工依次创建之外,还可以通过Maven插件来直接创建工程。
创建工程
创建Java工程
创建web工程
Maven工程目录结构
java工程与web工程对比:
5 第一个Maven项目(IDEA生成)
5.1 配置Maven
5.2 手工创建Java项目
IDEA中的构建命令,作用同mvn
可通过添加Maven运行环境,达到相同的命令效果。
添加之后,点击运行按钮即可执行相应的命令。
5.3 原型创建Java项目
5.4 原型创建Web项目
5.5 插件
启动Web工程需要用到Tomcat插件,在pom文件中添加以下Tomcat7插件。
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
添加之后可以看到,web项目中已经有了tomcat插件。
双击 tomcat7:run, 可启动服务器。
6 依赖管理
6.1 依赖配置
依赖指当前项目运行所需的jar,一个项目可以设置多个依赖。
格式:
<!-当前项目所依赖的所有jar-->
<dependencies>
<!-设置具体的依赖-->
<dependency>
<!-依赖所属群组id-->
<groupId>junit</groupId>
<!-依赖所属项目id-->
<artifactId>junit</artifactId>
<!-依赖版本号-->
<version>4.12</version>
</dependency>
</dependencies>
6.2 依赖传递
依赖包括直接依赖、间接依赖两种,且依赖具有传递性。
- 直接依赖:在当前项目中通过依赖配置建立的依赖关系。
- 间接依赖:被资源的资源如果依赖其他资源,当前项目间接依赖其他资源。
依赖传递冲突问题 - 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高。
- 声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的。
- 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的。
6.3 可选依赖(不透明)
可选依赖指对外隐藏当前所依赖的资源一一不透明。
将某依赖的<optional>
标签指定为true时,间接引用该依赖的项目将无法看到该依赖资源。
6.4 排除依赖(不需要)
排除依赖指主动断开间接依赖的资源,被排除的资源无需指定版本一一不需要。
6.5 依赖范围
依赖的jar默认情况可以在任何地方使用,可以通过scope标签设定其作用范围。 如下,表示junit依赖仅在测试代码中生效。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
scope的可选值有4种,分别为compile(默认值)、test、provided、runtime.它们在项目中的作用范围各不相同。
scope作用范围
- 主程序范围有效(main文件夹范围内)
- 测试程序范围有效(test文件夹范围内)
- 是否参与打包(package指令范围内)
7 生命周期与插件
7.1 项目构建生命周期
Maven构建生命周期描述的是一次构建过程经历经历了多少个事件。
Maven对项目构建的生命周期划分为3个阶段。
- clean生命周期:清理工作。
- default生命周期:核心工作,例如编译,测试,打包,部署等。
- site生命周期:产生报告,发布站点等。
clean构建生命周期
default构建生命周期
site构建生命周期
7.2 插件
- 插件与生命周期内的阶段绑定,在执行到对应生命周期时执行对应的插件功能。
- 默认maven在各个生命周期上绑定有预设的功能。
- 通过插件可以自定义其他功能。
例如:
<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>
</goals>
<phase>generate-test-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
其中的<phase>
标签指插件在Maven构建生命周期时的哪个阶段开始运行。以上的例子即,运行到default生命周期的generate-test-resources阶段时就要执行这个插件。
8 分模块开发与设计
8.1 工程模块与模块划分
如图,在企业开发中通常会将一个工程的各个模块拆分成独立的项目,把工程进行模块划分,一个模块只负责一块内容,模块之间通过接口进行通信,划分之后,一个工程会包含多个模块,每个人只需负责自己的模块即可。工程按模块开发,主模块ssm中无任何内容,所有的功能做成独立的模块,通过多个模块之间的合作完成整个工程。
ssm_pojo拆分
- 新建模块
- 拷贝原始项目中对应的相关内容到ssm_pojo模块中
ssm_dao拆分
- 新建模块
- 拷贝原始项目中对应的相关内容到ssm_dao模块中
- pom.xml:引入数据层相关坐标即可。直接依赖ssm_pojo(对ssm_pojo模块执行install命令,将其安装到本地仓库)
ssm_service拆分
- 新建模块
- 拷贝原始项目中对应的相关内容到ssm_service模块中
- pom.xml:引入数据层相关坐标即可。直接依赖ssm_dao(对ssm_dao模块执行install命令,将其安装到本地仓库),间接依赖ssm_pojo(有ssm_dao模块负责依赖关系的建立)
ssm_controller拆分
- 新建模块
- 拷贝原始项目中对应的相关内容到ssm_controller模块中
- pom.xml:引入数据层相关坐标即可。直接依赖ssm_service(对ssm_service模块执行install命令,将其安装到本地仓库),间接依赖ssm _dao、ssm_pojo(有ssm_service模块负责依赖关系的建立)
分模块开发小结
- 模块中仅包含当前模块对应的功能类与配置文件。
- spring核心配置根据模块功能不同进行独立制作。
- 当前模块所依赖的模块通过导入坐标的形式加入当前模块后才可以使用。
- web.xml需要加载所有的spring核心配置文件。
9 聚合
9.1 多模块构建维护
项目拆分成多个模块之后,各模块之间相互依赖,并发布到本地仓库中。但假如其中一个模块 如ssm_dao模块做了更新,重新进行了install操作,可能会由于这个模块的调整而致使其他模块无法使用。
针对这个问题,可以使用聚合的工作机制:增加一个新的模块,通过新模块来管理其他4个模块,当compile或install这个新模块时,其管理的4个模块会同时进行compile或install。
9.2 聚合
作用:
聚合用于快速构建maven工程,一次性构建多个项目/模块。
制作方式:
- 创建一个空模块,打包类型定义为pom
<packaging>pom</packaging>
- 定义当前模块进行构建操作时关联的其他模块名称。
<modules>
<module>../ssm_controller</module>
<module>../ssm_service</module>
<module>../ssm_dao</module>
<module>../ssm_pojo</module>
</modules>
注意事项:
参与聚合操作的模块最终执行顺序与模块间的依赖关系有关,与配置顺序无关。
执行结果:
如下图,当执行ssm模块的compile操作时,参与聚合操作的模块根据模块间的依赖关系依次执行了compile.
10 继承
10.1 模块依赖关系维护
通过聚合解决了快速构建的问题,但仍存在资源方面的问题。原始的各个模块可能会依赖一些相同的资源,比如ssm_service和ssm_dao都会用到spring-context,但它们可能因所使用的版本不一致而产生兼容问题。
针对这个问题,可以使用继承的工作机制。增加一个新的模块,管理下面4个模块的资源依赖。新的模块称为父模块,被管理资源依赖的模块称为子模块。在父模块指定所有子模块用到的依赖的资源和对应版本,子模块使用资源时指定依赖资源即可,无需再声明版本,解决资源版本一致性问题。
10.2 继承
作用:
通过继承可以实现在子工程中沿用父工程中的配置。
maven中的继承与java中的继承相似,在子工程中配置继承关系。
制作方式:
在子工程中声明其父工程坐标与对应的位置。
<!-- 定义该工程的父工程-->
<parent>
<groupId>com.itheima</groupId>
<artifactId>ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 填写父工程的pom文件 -->
<relativePath>../ssm/pom.xml</relativePath>
</parent>
10.3 继承依赖定义
在父工程中定义依赖管理。
<!--声明此处进行依赖管理 -->
<dependencyManagement>
<!--具体的依赖 -->
<dependencies>
<!--spring环境 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependencies>
<dependencyManagement>
10.4 继承依赖使用
在子工程中定义依赖关系,无需声明依赖版本,版本参照父工程中依赖的版本。
<dependencies>
<!--spring环境 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
10.5 继承的资源
10.6 继承与聚合
作用:
- 聚合用于快速构建项目。
- 继承用于快速配置。
相同点:
- 聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中。
- 聚合与继承均属于设计型模块,并无实际的模块内容。
不同点:
- 聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些。
- 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己。
继承小结:
- 定义在父工程中
- 使用在子工程中(无需配置version)
11 属性
11.1 版本统一的重要性
通过定义依赖的属性保证版本统一。
11.2 属性类别
- 自定义属性
作用:
等同于定义变量,方便统一维护。
定义格式:
<!--定义自定义属性 -->
<properties>
<spring.version>5.1.9.RELEASE</spring.version>
<junit.version>4.12</junit.version>
</properties>
调用格式:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
- 内置属性
作用:
使用maven内置属性,快速配置。
调用格式:
${basedir}
${version}
- Setting属性
作用:
使用maven配置文件setting.xml中的标签属性,用于动态配置。
调用格式:
${settings.localRepository}
- Java系统属性
作用:
读取Java系统属性。
调用格式:
${user.home}
系统属性查询方式:
mvn help:system
- 环境变量属性
作用:
使用maven配置文件setting.xml中的标签属性,用于动态配置。
调用格式:
${env.JAVA_HOME}
系统属性查询方式:
mvn help:system
12 版本管理
12.1 工程版本区分
12.2 工程版本
- SNAPSHOT(快照版本)
项目开发过程中,为方便团队成员合作,解决模块间相互依赖和时时更新的问题,开发者对每个模块进行构建的时候,输出的临时性版本叫做快照版本(测试阶段版本)。快照版本会随着开发的进展不断更新。
- RELEASE(发布版本)
项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本。
12.3 工程版本号约定
约定规范:
- <主版本>.<次版本>.<增量版本>.<里程碑版本>
- 主版本:表示项目重大架构的变更,如:spring5相较于spring4的迭代。
- 次版本:表示有较大的功能增加和变化,或者全面系统的修复漏洞。
- 增量版本:表示有重大漏洞的修复。
- 里程碑版本:表明一个版本的里程碑(版本内部)。
范例:
- 5.1.9.RELEASE
13 资源配置
13.1 资源配置多文件维护
之前已经通过属性的方式将工程中的版本都抽取到一起管理。此外,工程中还有jdbc的用户等一些自定义的属性,可以在pom文件中一起进行管理。
13.2 配置文件引用pom属性
作用:
在任意配置文件中加载pom文件中定义的属性。
调用格式:
${jdbc.url}
开启配置文件加载pom属性:
<!--配置资源文件对应的信息 -->
<resources>
<resource>
<!--设定配置文件对应的位置目录,支持使用属性动态设定路径-->
<directory>${project.basedir}/src/main/resources</directory>
<!--开启对配置文件的资源加载过滤-->
<filtering>true</filtering>
</resource>
</resources>
14 多环境开发配置
14.1 多环境兼容
很多情况下,生产环境、开发环境、测试环境的属性值配置各不同。因此需要在不同的环境上加载其对应的属性配置。达到多环境兼容的目的。
14.2 多环境配置
<!--创建多环境 -->
<profiles>
<!--定义具体的环境:生成环境 -->
<profile>
<!--定义环境对应的唯一名称 -->
<id>pro_env</id>
<!--定义环境中专用的属性值 -->
<properties>
<jdbc.url>jdbc:mysql://127.1.1.1:3306/ssm_db</jdbc.url>
</properties>
<!--设置默认启动 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!--定义具体的环境:开发环境 -->
<profile>
<id>dev_env</id>
……
</profile>
</profiles>
14.3 加载指定环境
作用:
加载指定环境。
调用格式:
mvn 指令 –P 环境定义id
范例:
mvn install –P pro_env
15 跳过测试
15.1 跳过测试环节的应用场景
- 整体模块功能未开发
- 模块中某个功能未开发完毕
- 单个功能更新调试导致其他功能失败
- 快速打包
15.2 三种跳过测试的方式
- 使用命令跳过测试
命令:
mvn 指令 –D skipTests
注意事项:
执行的指令生命周期必须包含测试环节。
- 使用界面操作跳过测试
- 使用配置跳过测试
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests><!--设置跳过测试 -->
<includes> <!--包含指定的测试用例 -->
<include>**/User*Test.java</include>
</includes>
<excludes><!--排除指定的测试用例 -->
<exclude>**/User*TestCase.java</exclude>
</excludes>
</configuration>
</plugin>
16 私服
16.1 分模块合作开发
现在将一个项目分模块进行开发,不同的开发者开发不同的内容,如果需要用到公共资源可以直接从中央仓库下载。如果开发者之间需要用到对方开发的资源。则可以建立一台公共的计算机(私服),开发者将资源上传到该计算机,即可实现小范围内的资源共享。私服必须与中央服务器分离开,虚线左侧可以理解为公司内部范围,虚线右侧为互联网范围。
16.2 私服搭建
Nexus
- Nexus是Sonatype公司的一款maven私服产品。
- 下载地址:https://help.sonatype.com/repomanager3/download
Nexus安装、启动与配置
-
启动服务器(命令行启动)
nexus.exe /run nexus
-
访问服务器(默认端口:8081)
http://localhost:8081
-
修改基础配置信息
安装路径下etc目录中nexus-default.properties文件保存有nexus基础配置信息,例如默认访问端口。 -
修改服务器运行配置信息
安装路径下bin目录中nexus.vmoptions文件保存有nexus服务器启动对应的配置信息,例如默认占用内存空间。
16.3 私服资源获取
16.4 仓库分类
-
宿主仓库hosted
保存无法从中央仓库获取的资源(自主研发/第三方非开源项目)
-
代理仓库proxy
代理远程仓库,通过nexus访问其他公共仓库,例如中央仓库。
-
仓库组group
将若干个仓库组成一个群组,简化配置。
仓库组不能保存资源,属于设计型仓库。
16.5 手动资源上传
上传资源时应提供对应的信息:
- 保存的位置(宿主仓库)
- 资源文件
- 对应坐标
16.6 idea环境中资源上传与下载
16.7 访问私服配置
本地仓库访问私服
- 配置本地仓库访问私服的权限(setting.xml)
<servers>
<server>
<id>heima-release</id>
<username>admin</username>
<password>admin</password>
</server>
<server>
<id>heima-snapshots</id>
<username>admin</username>
<password>admin</password>
</server>
</servers>
- 配置本地仓库资源来源(setting.xml)
<mirrors>
<mirror>
<id>nexus-heima</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
</mirrors>
项目工程访问私服
- 配置当前项目访问私服上传资源的保存位置(pom.xml)
<distributionManagement>
<repository>
<id>heima-release</id>
<url>http://localhost:8081/repository/heima-release/</url>
</repository>
<snapshotRepository>
<id>heima-snapshots</id>
<url>http://localhost:8081/repository/heima-snapshots/</url>
</snapshotRepository>
</distributionManagement>
- 发布资源到私服命令
mvn deploy
写在最后
本文为《黑马程序员——Maven从基础到高级应用》的学习笔记。
每当组内大佬调整了项目结构,我们拉个代码都是心惊胆战,生怕项目又跑不起来,缺这个配置少那个包。于是网上找来Maven教学视频过了一遍,内容也算比较系统全面了,平时项目中用到的知识基本都涉及到了。希望以后能学以致用,遇到问题丝毫不慌。