maven工具篇
Maven安装和核心概念
一、maven安装
介绍了一下maven需要安装的环境,比如说:操作系统、jdk版本要求(maven是基于java编写的)、内存情况等等。
然后就是修改环境变量等等信息。
附上一个学习连接:https://www.runoob.com/maven/maven-tutorial.html
安装完成之后,查看是否安装成功
二、Maven约定
要想使用maven,maven就给使用者定义规范,要求使用者来遵守规范。
1、必须有pom.xml文件
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
</project>
坐标:每个项目都需要有一个坐标,因为通过坐标可以定位到一个项目。坐标由三部分组成:
groupId:分组id,一般表示项目组织id,是哪个组织编写的
artifactId:当前项目的名称【约定】
version:当前项目的版本号。有SNAPSHOT(快照版)和RELEASE(发行版)
ps:
如果是引入外部的jar包,这里对应的是本地仓库中的位置,可以从本地仓库中找到。
3、编写java源文件位置
maven要求,要求在src/main/java目录下来编写源代码
3、编译class文件位置
maven要求,编译后的class会放置在target/class目录下
将源代码编译之后,会放置到target/clases目录下。
4、配置文件位置
maven要求配置文件写在src/main/resources目录下
配置文件在参与编译阶段之后,也会放置到类路径下
5、测试方法
要想让maven来跑我们的测试用例代码,测试类必须要在src/test/java目录下且以Test开头,测试类中的方法必须要以test开头
方法不要有返回值。
然后执行mvn test跑测试方法
在测试方法运行之后,会在控制台展示:正在测试哪个类,正在测试的成功数量,错误和跳过的。
在surefire-reports下会生成测试报告等等。有xml文件和txt文件等等条件。
6、使用junit依赖测试
首先需要在pom中引入依赖,官方上有一个,直接拿下来用。直接在pom文件中来进行添加
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
刷新maven,将依赖引入进来。
junit测试
maven约定:如果引入了junit包依赖,那么上面的测试约定就作废了,失效了。也就是说,方法、类名都可以不以test开头了。
即使不以test开头,依然是可以来进行运行的。
还可以针对里面的异常信息来做判断:
因为这里测试的1和1是不想等的,所以这里会报错。
三、依赖管理
依赖管理就是引入外界的,也就是第三方的jar包到当前项目中来。
在学习web的时候,我们处理第三方jar包的时候,是添加到web/lib目录下来进行管理。
而maven引入了包的依赖管理,方便我们来管理我们的引入的jar包。
maven中jar包位置
maven会先从本地仓库找,本地仓库找不到会从远程仓库下载。
正常开发过程中,首次使用maven的时候,去下载jar包的时候,本地肯定都是没有的,肯定都是从远程仓库来进行下载。
本地仓库
本地仓库是下载安装了maven之后,maven会给我们自动指定的。
找到maven的安装位置,我的是在C:\work\software\java\maven\conf,然后找到这个目录下的settings.xml配置文件。
搜索关键字:localRepository
看到一行配置:
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>D:/mavenr</localRepository>
默认是在当前用户目录下的.m2目录下的repository目录。
但是可能因为我们的C盘文件太小,或者是以为用户被注销了,导致无法使用本地仓库的情况,所以建议将本地仓库建立在其他目录下。
我这里选择建立的是在D盘下的mavenr目录下。
远程仓库
远程仓库一般来说,分为两种:公司自己搭建的仓库和maven中央仓库(但是在国外,下载速度较慢)
在私服中的jar包,是由开发人员手动来进行上传的。
私服一般是用来存当前公司中开发出来的公共组件,可以依赖的组件放入到私服中,让其他项目来引入。这种方法比较可取。
Maven核心配置
主要分为三个部分:
- 1、项目依赖(内部和外部)
- 2、项目聚合和继承
- 3、项目构建和配置
一、项目依赖
当前项目可能会依赖其他的项目,这里说的其他的项目,可能是简单的jar包,也可能是一个项目jar包,在体量上没有限制。
对于依赖的组件,maven通过maven特性来管理项目中引入的依赖
- 1、依赖传播
- 2、依赖优先原则
- 3、可选依赖
- 4、排除依赖
- 5、依赖范围
1、依赖传递
下面将会通过SpringMVC的依赖来做一个示范。
在idea中有一个快捷键,可以来查看当前项目的依赖图
下面拿commons-logging来举例子,当前的commons-logging版本可以在External Libiaries下面可以看到
当前版本是1.2
那么下面接着在pom文件中引入另外一个版本中的commons-logging版本
引入依赖之后,发现当前的commons-logging版本变成了最新的版本了。
maven依赖-就近原则
上面描述的就是就近原则,那么怎么来理解呢?再来生成对应的依赖树结构看下:
从这里可以看到,如果不引入commons-logging坐标,test项目需要依赖commons-logging的话,那么需要经过spring-webmvc来进行依赖。
但是我们新添加了commons-logging坐标之后,test项目就不需要经过spring-webmvc,而是直接依赖上了commons-logging
蓝色线条表示的是只有单个依赖,红色线条表示的是出现了多个依赖
也就是红色线条表示的信息,项目直接依赖了commons-logging,而spring-webmvc也依赖的是commons-logging
test项目直接使用了1.1.3版本
就近原则也就是说,当前项目依赖了同一个依赖,哪个依赖离当前项目越近,maven就会选择来利用哪一个依赖。
最短路径优先。
maven依赖-优先原则
相对于就近原则来说,如果路径是一样的,那么该选择哪一个依赖呢?
这也是经常会出现的一种问题。
一个项目依赖了另外一个项目,但是这两个项目有着同样的一种依赖。那么就有可能导致出现问题。
所以为了避免这种问题,spring也定义了一个规则:如果是路径一致,那么谁先配置,就使用谁的。
来模拟一种场景
分别看下两个的pom文件:
server.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
client.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.4</version>
</dependency>
</dependencies>
直接查看server的依赖树
对于server来说,依赖的spring-webmvc,需要依赖spring-web;
对于client来说,是直接依赖了spring-web的。
但是对于server来说,因为从server到spring-web的路径都是一样的。那么maven这时候是如何选择的?
根据谁先引入,选择谁。而在server.pom中,先引入的是client,所以当前的版本应该是5.3.4版本
那么我在这里,我更改一下顺序,再看一下:
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.8.RELEASE</version>
</dependency>
</dependencies>
修改了对应的顺序之后
可以看到现在依赖的是4.1.8的版本了。
看这里的黑线即可分辨出来依赖的是哪一个。
maven依赖-顺序原则
直接来看比较好:
后面的会覆盖掉前面的。
可选依赖
也可以用于上面的情况,比如在client中,设置spring-web为可选依赖,这样子,当client被server引入之后,就是可选可不选。
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.4</version>
<optional>true</optional>
</dependency>
</dependencies>
那么这个时候看一下server的依赖结构
这个时候,发现没有依赖使用到client中的,但是不影响server的使用。
排除依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.8.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
在当前版本中,排除对当前版本中对spring-web的依赖,而去依赖于其他的选项。
依赖范围
一些依赖在打包的时候没有必要打包进去,例如junit,只有在测试的时候才会用到。
maven可以通过scope属性来决定作用域范围,maven一共支持四种:
- compile:默认的作用域范围,在编译和打包都会依赖;
- provided:编译时会依赖,但是不会打包进去。如servlete-api
- runtime:打包时依赖,但是编译不会。如Mysql-connector
- test:测试范围,编译运行测试用例依赖,但是不会打包进去
- system:作用域由操作系统作用域决定。
二、聚合和继承
聚合是相当于父工程来说的,继承是相当于子项目来说的。
聚合在父工程中,一般都是选择版本号、插件等等;
但是依赖管理采用的使用
<dependencyManagement></dependencyManagement>
这样子的好处是让子类有选择的继承父类中的依赖,还不需要来使用版本号就可以使用了。