一、Maven的作用
依赖管理:自动管理项目所需要的依赖库,自动管理依赖的版本,避免同一个依赖库不同版本的冲突。
构建项目:可以管理项目的编译、测试、打包、部署等构建过程。
统一项目结构:提供标准的、统一的项目结构
二、Maven下载和安装
- 下载地址
下载地址:maven.apache.org/download.cg…
- 解压到任意位置
- 配置环境变量
- Maven 是用 Java 写的,因此需要配置JAVA_HOME
- 系统变量中新建一个MAVEN_HOME,值是Maven的安装目录
- 在Path中添加一个路径%MAVEN_HOME%\bin
- cmd中输入mvn,如果出现任务指令,则说明配置成功
三、Maven基本概念
1.Maven 软件路径介绍
- bin:可运行指令
- boot:里面有一个jar包,是Maven的类加载器
- conf:存放Maven的配置文件
- lib:存放Maven运行的jar包
2.仓库
用于存储资源,包含各种jar包
1.仓库的分类
- 远程仓库:为本地仓库提供资源
- 中央仓库:Maven官方的服务器,存放着所有的的jar包
- 私服:部门/公司范围内存储资源的仓库,从中央仓库获取资源
- 本地仓库:保存在自己计算机上的jar包
2.私服的作用
- 保存具有版权的资源,包含购买或自主研发的jar
- 中央仓库中的jar都是开源的,不能存储就有版权的资源
- 一定范围内共享资源,仅对内部开发,不对外共享
计算机先访问本地仓库,如果有直接获取;没有会让从私服获取;私服没有就回去访问中央仓库,私服获取之后,返回给本地服务器
2.坐标
1.坐标的概念
- 概念Maven中的坐标用于描述仓库中资源的位置
- 作用:通过该标识,可以将资源的识别与下载工作交给机器完成
2.坐标的主要组成
- groupId:当前Maven项目隶属组织名称+项目名(通常是域名反写,例如:org.mybatis)
- artifactId:定义当前Maven模块名称(通常是模块名称)
- version:定义当前版本号
- packaging:定义该项目的打包方式(不属于坐标的组成)
3.获取jar包的坐标
- 访问maven的仓库地址:mvnrepository.com
- 输入需要的jar包名称
- 选择jar包的版本号
- 新的页面中有一个Maven的框,复制即可
四、仓库配置
1、本地仓库配置
该配置用来指定资源下载到哪里
- 在任意位置创建一个文件夹
- 打开maven安装目录下的conf文件夹
- 打开里面的settings.xml文件
- 复制下面的代码到里面
<localRepository>创建的文件夹地址</localRepository>
2、远程仓库配置
该配置用来指定资源从哪里下载
- 打开maven安装目录下的conf文件夹
- 打开里面的settings.xml文件
- 找到mirror标签
- 复制注释中的一份到mirror标签中
<mirror>
<id>alicloud</id>
<name>aliyun</name>
<mirrorOf>central</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
五、第一个Maven项目(IDEA生成)
1.第一步:配置Maven
新建项目-->Empty Project
创建完成后修改项目的sdk
修改Maven的版本为自己下载的,并且覆盖掉Idea的配置文件为自己的
2.第二步:创建java项目
2.1 第一种:手工创建 Maven 项目
- 创建模块,选择Maven
- 选择填写模块的Maven的坐标,然后一路next
- 设置界面进入项目结构,给包配置对应的属性
- 进入pom.xml配置文件,打上需要用的jar包,写完之后需要点击右边的刷新
- 构建项目
2.2 第二种:使用Maven模板创建java工程
- 选择模块,新建一个maven模块,勾选Create From archetype(使用模板),然后选择quickstart
- 修改GroupId和ArtifactId,然后一路next
- 然后在项目目录的main、test包下新建resources包
- 右键新建的resources包,选择Mark Directory as--》Sources Root
2.3 第三种:使用Maven模板创建web工程
- 选择模块,新建一个maven模块,勾选Create From archetype(使用模板),然后选择webapp
- 修改GroupId和ArtifactId,然后一路next
- 在main包下创建java包,在src目录下创建test包,在test包下创建java、resources包
- 然后给包相应的颜色
3. 第三步:添加插件运行项目【可选】
- 修改模块下的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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<name>web01</name>
<groupId>com.junqing</groupId>
<artifactId>web01</artifactId>
<dependencies>
</dependencies>
</project>
- 打开maven坐标库,搜索
tomcat maven,找到org.apache.tomcat.maven的包,复制依赖 - 在
pom.xml文件的build标签中的plugins标签中新增加一个plugin标签,如果没有就字节写一部分,把赋值的依赖粘贴进去,如下面代码所示,然后配置启动端口和路径
<!--构建-->
<build>
<!--设置插件-->
<plugins>
<!--设置具体插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
- 然后刷新maven,加载资源
- 然后使用maven的tomcat插件,运行项目,启动成功之后就会给一个地址,点击就可以访问项目
- 如果需要修改端口:在配置第 3 步里面添加configuration标签
<!--配置-->
<configuration>
<!--修改端口号-->
<port>80</port>
<!--修改路径-->
<path>/</path>
</configuration>
- 如果嫌启动麻烦:可以配置一个按钮
- 最终的
pom文件如下
<?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/maven-v4_0_0.xsd">
<!--指定pom的模型版本(不用修改)-->
<modelVersion>4.0.0</modelVersion>
<!--打包方式:web工程为war,java工程为jar-->
<packaging>war</packaging>
<!--name没用-->
<name>Test02</name>
<!--通常为域名反写-->
<groupId>com.junqing</groupId>
<!--项目id:通常是项目名-->
<artifactId>Test02</artifactId>
<!--版本号(随便写):release(完成版),SNAPSHOT(开发版)-->
<version>1.0-SNAPSHOT</version>
<!--设置当前工程的所有依赖-->
<dependencies>
<!--当前工程的具体依赖-->
<dependency>
<groupId></groupId>
<artifactId></artifactId>
</dependency>
</dependencies>
<!--构建-->
<build>
<!--设置插件-->
<plugins>
<!--设置具体插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<!--配置-->
<configuration>
<!--修改端口号-->
<port>80</port>
<!--修改路径-->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
六、依赖管理
依赖的概念:指当前项目运行所需要的jar,一个项目可以设置多个依赖
1.项目依赖配置
配置依赖的方式:在pom.xml中的 dependencies 中添加 dependency(可以有多个)
<dependencies>
<!--具体依赖(可以有多个)-->
<dependency>
<groupId>log4j</groupId><!--群组id-->
<artifactId>log4j</artifactId><!--项目id-->
<version>1.2.14</version><!--版本号-->
</dependency>
<!--第二个具体依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2.依赖传递
1.依赖传递的概念
- 场景解释:项目 1 需要用到项目 2,这个时候需要把项目 2 作为依赖配置到项目 1 中。这个时候项目 1 中引用到的依赖同时也会被项目 2 引用
- 直接依赖:在当前项目中通过配置依赖建立的依赖关系【项目 2 依赖项目 1】
- 间接依赖:通过依赖传递,传递过来可以用的【项目 2 间接依赖项目 1 中使用到的依赖】
2.依赖传递的配置方法
把被调用的项目坐标配置到调用项目的dependency中(项目坐标:group、artifactId、version),被调用的项目坐标也会通过依赖传递引用过来
<!--配置依赖-->
<dependency>
<groupId>com.junqing</groupId>
<artifactId>Test01</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.依赖传递冲突问题
- 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高
- 声明优先:当资源在同层被依赖时,谁先被配置,谁先被使用
- 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的【同一个配置文件,同一个软件配置了两个版本,后面的覆盖前面的】
3.可选依赖
- 可选依赖的概念:对外隐藏当前所依赖的资源(别人能不能看见)
- 场景解释:项目 1 有一个依赖,不想让其他项目也引用这个依赖,于是主动使用
option标签隐藏了起来。后面项目 2 引用项目 1 的时候,这个被隐藏的依赖不会被引入到项目 2 中- 可选依赖操作:对应的依赖中加一个optional标签即可
<dependency>
<groupId>com.junqing</groupId>
<artifactId>Test01</artifactId>
<version>1.0-SNAPSHOT</version>
<optional>true</optional><!--隐藏起来,别人就看不见了-->
</dependency>
4.依赖排除
- 依赖排除的概念:主动断开依赖的资源(主动排除另一个项目的某个依赖)
- 场景解释:项目 2 引入了项目 1,但是项目 1 中的某个依赖项目 2 不想要,于是项目 2 主动把项目 1 中某个依赖排除了
- 依赖排除操作:引入依赖的时候加上一个
exclusions标签,然后里面使用exclusion排除指定依赖
案例:项目 1 中的log4j依赖,项目2不需要,因此在项目 2 的依赖中排除掉项目 3 的log4j
<!--不要它里面的log4j-->
<dependency>
<groupId>com.junqing</groupId>
<artifactId>Test01</artifactId>
<version>1.0-SNAPSHOT</version>
<!--依赖排除-->
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
5.依赖范围
依赖的jar默认情况可以在任何地方使用,可以通过scope标签设定其作用范围
作用范围
- 主程序范围有效(main文件夹范围内)
- 测试程序范围有效(test文件夹范围内)
- 是否参与打包(package指令范围内)
6.依赖范围传递性(了解即可)
带有依赖范围的资源在进行传递时,作用范围将受到影响
七、生命周期与插件
- 各个构件环节执行的顺序不能被打乱,必须按照规定的正确顺序来执行
- Maven的核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务由插件来完成
- Maven核心程序为了更好的实现自动化构建,按照这样的特点执行生命周期中的各个阶段:不论要执行哪一阶段,都会从第一步开始执行(生命周期的第一步开始)
1.项目构建生命周期
- clean:清理工作
- default:核心工作,例如编译,测试,打包,部署
- site:产生报告,发布站点
1.1、clean生命周期
- pre-clean:执行一些需要在clean之前完成的工作
- clean:移除上一次构建生成的文件
- post-clean:执行一些需要在clean之后立刻完成的工作
1.2、default(构建)生命周期
1.3 特别说明
执行后置的声明周期执行的时候会把前面的声明周期都执行
例如:
- test会把上面的都执行
- package会把他上面的都执行
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-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
八、分模块开发
1.分模块开发概念
原本一个项目里面有 DTO、Service、Controller 包,现在给他拆分成几个模块,多个模块中相互引用完成整体功能。
2.模块具体拆分过程
- pojo 模块:直接将实体类复制过来。为了给其他模块使用,因此还需要执行
install,将包保存到本地仓库。 - dao 模块:将类及配置文件复制过来,然后将需要的依赖写入配置文件。由于需要实体类,因此配置文件中还需要需要引入 pojo 模块。
- service 模块:基本跟 dao 层操作类似。
- controller 模块:基本跟 dao 层操作类似
九、聚合
使用场景:我们现在已经把一个项目拆分成了多个模块,并且每个模块都
install到了本地仓库中。现在的问题是多个模块之间都有依赖,其中一个模块更新之后,其他的模块不知道这个模块的更新。因此,是否可以有一个模块管理这几个模块之间的合作。结论:将这几个模块都移动到父模块中,父模块管理这几个子模块
- 创建一个父模块,由于父模块没有代码,因此 src 可以删除。
- 父模块的
pom文件,packaging标签的值改为pom
<packaging>pom</packaging>
- 父模块
pom文件,新增modules标签,然后里面新增module模块用来指定管理哪些模块
<modules>
<module>模块1的名字</module>
<module>模块2的名字</module>
<module>模块3的名字</module>
<module>模块4的名字</module>
</modules>
- 后面其他模块代码进行改动的时候,编译、安装父模块即可
十、继承
使用场景:一个项目拆分成多个模块之后,两个模块之间可能会引用同一个技术的不同版本。例如:模块 1 使用了 spring 5.1.9,模块 2 使用了 spring 5.2.0。不同版本之间可能会出现兼容性问题。因此,是否可以有一个模块管理其他模块使用技术的版本。
结论:父工程定义使用的技术,及版本号。子模块需要使用什么技术,直接声明技术名就行,版本号直接使用父模块定义的。
- 父模块的
pom文件 新增dependencyManagement标签和dependencies,用来声明,子模块可以使用哪些技术。
<!--声明对依赖进行版本管理-->
<dependencyManagement>
<!--声明管理哪些依赖-->
<!--技术1-->
<dependencies>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</dependencies>
<!--技术2-->
<dependencies>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</dependencies>
<!--技术3-->
<dependencies>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
</dependencies>
</dependencyManagement>
- 子模块的
pom文件,新增parent标签,用来声明父模块是谁
<parent>
<groupId>父模块groupId</groupId>
<artifactId>父模块artifactId</artifactId>
<version>父模块version</version>
<!--relativePath 用来说明父模块的pom文件在哪里-->
<relativePath>父模块pom文件路径</relativePath>
</parent>
- 子模块的
pom文件中,dependency标签中的version就可以删除了 - 父模块的
pom文件中,build标签新增pluginManagement标签,用来管理插件
<build>
<pluginManagement>
<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-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
- 子模块的
pom文件中,build标签,只用写必要的信息即可
十一、属性
使用场景:父模块中声明的依赖,可能有很多技术的版本号一致,其中一个修改其他的也需要同步修改。因此,如果我们一个一个该,可能会漏掉,因此是否有一个方案,能解决改一个地方,其他地方同步修改呢?
结论:在 pom 文件中,定义属性,其他地方引用属性即可。如果属性修改了,其他引用属性的地方会同步修改
- 在
pom文件中使用properties标签,在其内部自定义属性
<properties>
<spring.version>5.1.9</spring.version>
<project.version>1.0</project.version>
</properties>
- 需要使用的地方 使用
${自定义属性名}引用自定义属性即可
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<!--使用${}引用自定义属性-->
<version>${spring.version}</version>
</dependency>
十二、私服
1.Nexus 下载
Nexus 是一款 Maven 私服产品
下载地址:直接 docker 下载
2.仓库分类
- 宿主仓库(hosted):保存无法从中央仓库获取的资源【存放自主研发、第三方非开源项目】
- 代理仓库(proxy):访问其他公共仓库【如访问中央仓库】
- 仓库组(group):将若干仓库组成一个群组,简化配置【不保存资源,属于理论存在的仓库】
3.创建仓库
- 点击设置找到仓库,点击添加仓库
- 选择仓库类型,这里我创建了一个宿主仓库
- 录入仓库名字,仓库类型,然后点击确定
- 然后主页就显示出来了
- 点击 maven-public,将我们新创建的仓库添加到组中
4.手动上传依赖
- 选中我们自己创建的仓库
- 点击上传
- 将我们自己的 jar 包选中,然后录入依赖的坐标,即可完成
5.本地访问私服配置
- 在 Maven 的
setting配置文件中找到servers标签。配置私服的地址及账号密码
<servers>
<server>
<!--id可以随便-->
<id>myDevRep</id>
<username>admin</username>
<password>123456</password>
</server>
</servers>
- 在 Maven 的
setting配置文件中找到mriiors标签,配置哪些资源从私服下载
<!--如果配置了多个仓库地址,会从上往下找资源-->
<mirrors>
<!--之前配置-->
<mirror>
<id>alicloud</id>
<name>aliyun</name>
<mirrorOf>central</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
<!--本次配置的-->
<mirror>
<!--id随便-->
<id>myRep</id>
<!--name随便-->
<name>myRep</name>
<!--mirrorOf:表示哪些资源从这个仓库下载(central-表示中央仓库的资源 *-表示所有资源)-->
<mirrorOf>*</mirrorOf>
<!--群组的url:从nexus中复制-->
<url>http://127.0.0.1:8081/repository/maven-public/</url>
</mirror>
</mirrors>
6.IDEA 资源上传、下载
IDEA 资源下载是走的 Maven,在上面我们已经给 Maven 私服配置好了,因此这里只需要配置资源上传。
- 在项目的
pom.xml中增加distributionManagement标签,然后正式版依赖仓库信息用repository标签,快照版的依赖仓库信息用snapshotRepository标签
<distributionManagement>
<!--正式版本依赖仓库-->
<repository>
<!--Maven中server中配置的id-->
<id>myDevRep</id>
<!--仓库地址:从私服中复制过来即可-->
<url></url>
</repository>
<!--标准版本仓库依赖-->
<snapshotRepository>
<!--Maven中server中配置的id-->
<id></id>
<!--仓库地址:从私服中复制过来即可-->
<url></url>
</snapshotRepository>
</distributionManagement>
- 运行 Maven 的
deploy声明周期即可将依赖发布到对应仓库