1. Maven 是什么
Maven 是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),反映在配置中,就是一个 pom.xml 文件。是一组标准集合,一个项目的生命周期、一个依赖管理系统,另外还包括定义在项目生命周期阶段的插件(plugin)以及目标(goal)。
当我们使用 Maven 的使用,通过一个自定义的项目对象模型,pom.xml 来详细描述我们自己的项目。
Maven 中的有两大核心:
- 依赖管理:对 jar 的统一管理(Maven 提供了一个 Maven 的中央仓库,https://mvnrepository.com/,当我们在项目中添加完依赖之后,Maven 会自动去中央仓库下载相关的依赖,并且解决依赖的依赖问题)
- 项目构建:对项目进行编译、测试、打包、部署、上传到私服等
2. Maven 安装
Maven 是 Java 项目,因此必须先安装 JDK。
下载 Maven:下载地址:http://maven.apache.org/download.cgi
- 解压并配置
配置,只需要配置环境变量即可:
首先配置 MAVEN_HOME:
然后配置环境变量:
- 检验安装
如果使用了 IntelliJ IDEA ,可以不用去额外下载 Maven,直接使用 IDEA 中自带的 Maven 插件即可。IntelliJ IDEA 中自带的 Maven 插件在 \ideaIU-2019.2.4.win\plugins\maven\lib\maven3
3. Maven 配置
maven的conf目录中有 settings.xml ,是maven的配置文件,实际上,没有特殊需求的话,安装好之后直接就可以用了。一般来说,还是需要稍微配置一下,
- Maven默认使用国外的中央仓库,下载依赖速度过慢,所以都会配置一个国内的公共仓库(阿里巴巴的仓库)替代中央仓库。
- 我们可以自定义一个目录作为本地仓库,Maven下载的所有依赖都会保存在这个目录中。
- 配置私服 ,如果公司搭建了的自己 Maven 私服 (这个仓库中存放 一般就是公司内部自己开发的 jar)这时我们就要配置私服让他去私服下载依赖。
我现在用的settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 本地仓库的位置 -->
<localRepository>F:/repository</localRepository>
<!-- Apache Maven 配置 -->
<pluginGroups/>
<proxies/>
<!-- 私服发布的用户名密码 -->
<servers>
<server>
<id>releases</id>
<username>deployment</username>
<password>He2019</password>
</server>
<server>
<id>snapshots</id>
<username>deployment</username>
<password>He2019</password>
</server>
</servers>
<!-- 阿里云镜像 -->
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<!-- https://maven.aliyun.com/repository/public/ -->
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<!-- 配置: java8, 先从阿里云下载, 没有再去私服下载 -->
<!-- 20190929 hepengju 测试结果: 影响下载顺序的是profiles标签的配置顺序(后面配置的ali仓库先下载), 而不是activeProfiles的顺序 -->
<profiles>
<!-- 全局JDK1.8配置 -->
<profile>
<id>jdk1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<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>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
<!-- Nexus私服配置: 第三方jar包下载, 比如oracle的jdbc驱动等 -->
<profile>
<id>dev</id>
<repositories>
<repository>
<id>nexus</id>
<url>http://nexus.hepengju.cn:8081/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>Public Repositories</name>
<url>http://nexus.hepengju.cn:8081/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>
</profile>
<!-- 阿里云配置: 提高国内的jar包下载速度 -->
<profile>
<id>ali</id>
<repositories>
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<!-- 激活配置 -->
<activeProfiles>
<activeProfile>jdk1.8</activeProfile>
<activeProfile>dev</activeProfile>
<activeProfile>ali</activeProfile>
</activeProfiles>
</settings>
仓库类型
仓库类型 | 说明 |
---|---|
本地仓库 | 就是你自己电脑上的仓库,每个人电脑上都有一个仓库,默认位置在 当前用户名\.m2\repository |
私服仓库 | 公司可以通过 Nexus来创建、管理一个私服,不对外开发。 |
中央仓库 | 有 Apache 团队来维护,包含了大部分的 jar, |
现在存在 3 个仓库,那么 jar 包如何查找呢?
4. Maven 常用命令
Maven 中有一些常见的命令,如果使用 Eclipse 需要手动敲命令,如果使用 IDEA 的话,可以不用命令,直接点点点就可以了。
常用命令 | 中文含义 | 说明 |
---|---|---|
mvn clean | 清理 | 这个命令可以用来清理已经编译好的文件 |
mvn compile | 编译 | 将 Java 代码编译成 Class 文件 |
mvn test | 测试 | 项目测试 |
mvn package | 打包 | 根据用户的配置,将项目打成 jar 包或者 war 包 |
mvn install | 安装 | 手动向本地仓库安装一个 jar |
mvn deploy | 上传 | 将 jar 上传到私服 |
这里需要注意的是,这些命令都不是独立运行的,它有一个顺序。举个简单例子:
我想将 jar 上传到私服,那么就要构建 jar,就需要执行 package 命令,要打包,当然也需要测试,那就要走 mvn test 命令,要测试就要先编译……,因此,最终所有的命令都会执行一遍。不过,开发者也可以手动配置不执行某一个命令,这就是跳过。一般来是,除了测试,其他步骤都不建议跳过。
当然,如果开发者使用了 IDEA ,这些命令不用手动敲,点一下就行:
5、Idea-Maven
在Idea中关联Maven
在idea中关联本地安装的maven,后续就可以通过idea使用maven,管理项目啦。
在全局设置中,关联Maven |
---|
创建Maven项目
如下选项 |
---|
设置项目名 |
---|
项目位置如下 |
---|
项目结构如下: |
---|
6. Maven 依赖管理
Maven 项目,如果需要使用第三方的控件,都是通过依赖管理来完成的。这里用到的一个东西就是 pom.xml 文件,概念叫做项目对象模型(POM,Project Object Model),
Maven 坐标
<dependencies> //在 dependencies 标签中,添加项目需要的 jar 所对应的 maven 坐标。
<dependency> //一个 dependency 标签表示一个坐标
<groupId>junit</groupId> //groupId 团体、公司、组织机构等等的唯一标识。团体标识的约定是它以创建这个项目的组 织名称的逆向域名。如 apache 的 groupId 是 org.apache.
<artifactId>junit</artifactId> //artifactId 相当于在一个组织中项目的唯一标识符。
<version>4.11</version> //version项目的版本。一个项目可能会有多个版本。如果是正在开发的项目,我们可以给 版本号加上一个 SNAPSHOT,表示这是一个快照版(新建项目的默认版本号就是快照版)
<scope>test</scope> //scope:表示依赖的使用范围
</dependency>
</dependencies>
scope:表示依赖范围。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2DuyztDg-1631030255573)(C:/Users/Administrator/Desktop/%E5%B8%B8%E7%94%A8%E6%96%87%E4%BB%B6/%E7%AC%94%E8%AE%B0/%E7%AC%94%E8%AE%B02/Redis/Pictures/6-1.png)]
我们添加了很多依赖,但是不同依赖的使用范围是不一样的。最典型的有两个,一个是数据库驱动,另一个是单元测试。
-
数据库驱动,在使用的过程中,我们自己写代码,写的是 JDBC 代码,只有在项目运行时,才需要执行 MySQL 驱动中的代码。所以,MySQL 驱动这个依赖在添加到项目中之后,可以设置它的 scope 为 runtime,编译的时候不生效。
-
单元测试,只在测试的时候生效,所以可以设置它的 scope 为 test,这样,当项目打包发布时,单元测试的依赖就不会跟着发布。
依赖冲突
- 依赖冲突产生的原因:在项目开发中使用Maven管理Jar包时,常常会遇到Jar包依赖冲突。其根本原因是不同Jar包引用了同一Jar包的不同版本。
当系统编译加载时,由于maven对jar包的依赖次序不同,系统可能编译加载 c.jar(1.2版本) ,也可能编译加载 c.jar(1.4版本) 。
- 当编译加载c.jar(1.4版本) 时,由于很多 jar 包都支持向下兼容,即高版本兼容低版本,因此不论 d.jar 调用 c.jar 还是 b.jar 调用 c.jar 一般都不会出问题。
- 当编译加载c.jar(1.2.版本) 时,那么 b.jar 调用Method A() 时则会报 NoSuchMethodError 异常,因为 Method A() 函数只存在于高版本的 c.jar 中,而此时系统编译加载的却是低版本的 c.jar 。上面所描述的情况便是所谓的依赖冲突问题。
冲突解决
- 先定义先使用
- 路径最近原则(直接声明使用)
以 spring-context 为例,下图中 x 表示失效的依赖(优先级低的依赖,即路径近的依赖优先使用):
上面这两条是默认行为。
我们也可以手动控制。手动控制主要是通过排除依赖来实现,如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
这个表示从 spring-context 中排除 spring-core 依赖。
7. Maven 私服
Maven 仓库管理也叫 Maven 私服或者代理仓库。使用 Maven 私服有两个目的:
- 私服是一个介于开发者和远程仓库之间的代理
- 私服可以用来部署公司自己的 jar
Nexus 介绍
Nexus 是一个强大的 Maven 仓库管理工具,使用 Nexus 可以方便的管理内部仓库同时简化外部仓库的访问。官网是:https://www.sonatype.com/
安装
- 下载
下载地址:https://www.sonatype.com/download-oss-sonatype
- 解压
将下载下来的压缩包,拷贝到一个没有中文的路径下,然后解压。
- 启动
解压之后,打开 cmd 窗口(以管理员身份打开 cmd 窗口),然后定位了 nexus 解压目录,执行 nexus.exe/run 命令启动服务。
这个启动稍微有点慢,大概有 1 两分钟的样子
启动成功后,浏览器输入 http://lcoalhost:8081 打开管理页面。
打开管理页面后,点击右上角上的登录按钮进行登录,默认的用户名/密码是 admin/admin123。当然,用户也可以点击设置按钮,手动配置其他用户。
点击 Repositories 可以查看仓库详细信息:
仓库类型
名称 | 说明 |
---|---|
proxy | 表示这个仓库是一个远程仓库的代理,最典型的就是代理 Maven 中央仓库 |
hosted | 宿主仓库,公司自己开发的一些 jar 存放在宿主仓库中,以及一些在 Maven 中央仓库上没有的 jar |
group | 仓库组,包含代理仓库和宿主仓库 |
virtual | 虚拟仓库 |
上传 jar
上传 jar,配置两个地方:
- Maven 的 conf/settings.xml 文件配置:
<server>
<id>releases</id>
<username>admin</username>
<password>admin123</password>
</server>
<server>
<id>snapshots</id>
<username>admin</username>
<password>admin123</password>
</server>
在要上传 jar 的项目的 pom.xml 文件中,配置上传路径:
<distributionManagement>
<repository>
<id>releases</id>
<url>http://localhost:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>http://localhost:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
配置完成后,点击 deploy 按钮,或者执行 mvn deploy 命令就可以将 jar 上传到私服上。
下载私服上的 jar
直接在项目中添加依赖,添加完成后,额外增加私服地址即可:
<repositories>
<repository>
<id>local-repository</id>
<url>http://localhost:8081/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
8. 聚合工程
所谓的聚合工程,实际上也就是多模块项目。在一个比较大的互联网项目中,项目需要拆分成多个模块进行开发,比如订单模块、VIP 模块、支付模块、内容管理模块、CMS、CRM 等等。这种拆分方式,实际上更接近于微服务的思想。在一个模块中,还可以继续进行拆分,例如分成 dao、service、controller 等。
有人可能会说,这个分包不就行了吗?
小项目当然可以分包,大项目就没法分包了。比如,在一个大的电商系统中,有一个子模块叫做用户管理、还有一个子模块叫做订单管理,这两个子模块都涉及到用户,像这种情况,我们就需要将用户类单独提取出来,做成单独的模块,供其他模块调用。
多模块项目展示
|--javaboy-parent
|-- javaboy-cms
|-- javaboy-crm
|-- javaboy-manger
|-- javaboy-manager-model
|-- javaboy-manager-dao
|-- javaboy-manager-service
|-- javaboy-manager-web
以 javaboy-manger 为例,javaboy-manager 本身并不提供功能,它只负责管理他自己的子模块,而他的子模块每一个都无法独立运行,需要四个结合在一起,才可以运行。项目打包时,model、dao、service 都将打包成 jar,然后会自动将打包好的 jar 复制到 web 中,再自动将 web 打包成 war 包。
IDEA 中创建聚合工程
1.创建一个空的 Maven 项目:
项目创建完成后,由于 parent 并不参与业务的实现,只是用来管理它的子模块,因此,src 目录可以将其删除。
2.选中当前工程,右键单击,New->Module
然后继续选择创建一个 Maven 项目:
在 IDEA 中,已经默认指明了当前 Module 的 parent,开发者只需要填入当前 Module 的 artifactId 即可:
javaboy-manager 创建完成后,此时,观察 javaboy-parent 的 pom.xml 文件,发现它自动加上了 packing 属性:
其中,它的 packaging 属性值为 pom,这表示它是一个聚合工程,同时,他还多了 modules 节点,指明了它自己的子模块。 同时,注意 javaboy-manager ,它自身多了一个 parent 节点,这个 parent 节点描述了它的父模块的属性值:
<parent>
<artifactId>javaboy-parent</artifactId>
<groupId>org.javaboy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
这个 parent 不仅仅是一个简单的父子关系描述,它存在继承关系,一般我们可以在 parent 中统一定义依赖或者插件的版本号
3.由于 javaboy-manager 本身也是一个聚合工程,因此,javaboy-manager 的 src 目录也可以删除。
4.选中 javaboy-manager,右键单击,New->Module 创建一个新的 Maven 模块出来。这个步骤类似于第二步,不在赘述。 这里,新的 javaboy-manager-model 创建成功后,我们手动配置它的 packaging 属性值为 jar。
5.依照第 4 步,再分别创建 javaboy-manager-service 以及 javaboy-manager-dao
6.继续创建 javaboy-manager-web 模块,不同于其他模块,web 模块需要打包成 war。
7.web 工程创建完成后,完善模块之间的继承关系。
javaboy-manager-web 依赖 javaboy-manager-service javaboy-manager-service 依赖 javaboy-manager-dao javaboy-manager-dao 依赖 javaboy-manager-model
注意,依赖默认是有传递性的,即在 javaboy-manager-dao 中依赖了 javaboy-manager-model,在 javaboy-manager-service 也能访问到。
配置后的依赖关系如下图:
有一个需要注意的地方,在多模块项目中,web 项目打包需要注意以下问题:
- 不可以直接单独打包
- 如果要打包,有两种方式:
- 第一种就是先手动挨个将 model、dao、service 安装到本地仓库
- 从聚合工程处打包,即从 web 的parent 处打包。
9.常见错误
Maven依赖爆红
找到本地仓库中的jar包,将仓库中的_remote.repositories
和lastUpdate
文件删掉,然后对该模块进行reimport
操作,然后关闭idea,重新打开,就好了。