Maven 笔记
1、配置(3.5.2版本)
1.1、环境变量配置
- JAVA_HOME
- MAVEN_HOME
1.2、maven目录结构
- bin:存放shell脚本和cmd脚本的目录,在命令行执行的mvn命令实际上执行的是这些文件
- boot:只存放一个文件(plexus-classworlds-2.5.2.jar),这是加载maven的类库的类加载器jar包,配置文件是bin目录下的m2.conf
- conf:包括maven的log配置、全局配置(settings.xml)、工具链配置
- lib:maven自身的jar包
- LICENSE:许可证文件
- NOTICE:maven使用的第三方软件介绍
- README.txt:maven介绍
1.3、设置HTTP代理
在settings.xml的下配置代理
2、POM
2.1、POM简介
POM(Project Object Model)文件是xml格式的文件,定义了项目的基本信息以及项目的依赖、构建信息等等
2.2、POM基本信息
modelVersion:对于maven2+/3+版本都是4.0.0
groupId:项目所在的实际项目,通常应该与你所在的组织或公司以及项目名有关,因为artifactId只定义maven项目的模块,如果groupId只有公司组织名而没有大项目名的话,groupId和artifactId加起来会比较难定义坐标。一般是域名的倒写,类似Java的包名,不是绝对的
artifactId:项目在组内的唯一ID
version:该项目的版本
groupId、artifactId、version共同组成一个坐标来唯一确定该项目在仓库中的位置
packaging:打包方式,可选,默认为jar
name:项目名字,可选
classifier:帮助定义输出附属的组件,如source或者javadoc,不能直接在这定义
dependencies:配置各种依赖
- dependency是它的子节点
- groupId:依赖所在的组的ID
- artifactId:依赖在组内的唯一ID
- version:该依赖的版本
- scope:该依赖在哪个生命周期被运用,不是必须的,默认是compile,对测试代码和运行代码都有效
- build:配置各种构建的信息
- plugins:配置各种插件
- plugin:插件
- groupId:插件所在的组的ID
- artifactId:插件在组内的唯一ID
- configuration:插件的配置
- source:源代码的JDK版本
- target:class编译到的JDK版本
3、Maven生命周期
3.1、编写代码
按照maven的定义,源代码在src/main/java包下
3.2、编译
cmd: mvn (clean) compile
3.3、测试
cmd: mvn (clean) test
按照maven的定义,测试的类在src/test/java包下
surefire 插件用来在maven构建生命周期的test phase执行一个应用的单元测试。它会产生两种不同形式的测试结果报告:
- 纯文本
- xml文件格式的
默认情况下,这些文件生成在工程的${basedir}/target/surefire-reports,目录下(basedir指的是pom文件所在的目录)。 它可以运行任何testNG,Junit,pojo写的单元测试
3.4、打包运行
cmd : mvn (clean) package
测试之后的生命周期是打包,打包的命名规范是:artifact-version.jar(war)
默认生成的jar无法运行,因为META-INFO/MANIFEST.MF中没有Main-Class信息,需要在节点下配置maven-shade-plugin插件
3.5、安装
cmd : mvn (clean) install
maven的install可以将项目本身编译并打包到本地仓库,这样其他项目引用本项目的jar包时不用去下载jar包,直接从本地就可以拿到刚刚编译打包好的项目的jar包,很灵活
3.6、根据Archetype生成项目骨架
cmd:mvn archetype:generate
Maven的规约是项目根目录下放置POM文件,src/main/java放置项目的源代码,src/test/java放置测试的源代码,src/main/resource放置项目的配置文件之类,src/test/resource放置测试的配置文件
4、Maven坐标&依赖
groupId、artifactId、version共同组成一个坐标来唯一确定该项目在仓库中的位置
当正确配置maven的依赖后,maven会从中央仓库下载对应的依赖
相关信息在已在 ## 2.2 提到
maven打出来的包名一般按照artifactId-version[-classifier].packaging的规约生成
4.1、依赖(dependency)的具体元素
- groupId
- artifactId
- version
- type:可以不声明,默认为jar
- scope:可以不声明,默认为compile
- optional:表示依赖是否可选
- exclusions:排除传递性依赖
4.2、依赖范围(scope)
compile:对于编译、测试、运行三种生命周期的test/main下的源代码都有效,默认为这个
test:只对于测试的生命周期的test目录下的代码有效,如JUnit
provided:对于编译、测试两种生命周期的test/main下的源代码都有效,如servlet-api,容器可以提供这个,所以运行时不用maven提供依赖
runtime:测试和运行时的test/main下的代码有效,如JDBC驱动
system:对于编译、测试两种生命周期的test/main下的源代码都有效,但是要与本机的系统路径绑定,一致性不强,也不是由maven仓库解析
<dependency> .... <scope>system</scope> <systemPath>${java.home}/lib/rt.jar</systemPath> </dependency>
import:导入依赖范围,不对依赖的生命周期不会有实际影响
4.3、传递性依赖
A依赖B,B依赖C,那么C就是A的传递性依赖
- 当第二直接依赖的范围是compile时,传递性依赖的范围与第一直接依赖一致
- 当第二直接依赖的范围是test时,传递性依赖不会得到传递
- 当第二直接依赖的范围是provide时,只传递第一直接传递范围为provide的依赖,且范围也是provide
- 当第二直接依赖的范围是runtime时,传递性依赖范围与第一直接依赖范围一致,但compile不一样,传递依赖为runtime
4.4、依赖调解
有如下依赖路径:
A -> B -> C -> X (1.0)
A -> D -> X (2.0)
两条路径都引用了X,此时Maven会选用最短路径原则,那么第二条路径会被运用
有如下依赖路径:
A -> C -> X (1.0)
A -> D -> X (2.0)
两条路径都引用了X,且路径长度一致,此时Maven会选用最先声明原则,在pom文件先声明的依赖会被启用,那么第一条路径会被运用
4..5、排除传递性依赖
排除依赖只需要groupId和artifactId
<dependency>
....
<exclusions>
<exclusion>
<groupId>···</groupId>
<artifactId>···</artifactId>
</exclusion>
</exclusions>
</dependency>
4.6、依赖归类
同一项目的不同包可能优势用的版本是一样的,我们可以用Maven的属性来进行统一管理
<properties>
<a.version>1.0.0</a.version>
</properties>
然后在dependency的version中使用${a.version}引用即可
4.7、优化依赖
Maven会解析项目的直接依赖和传递依赖,并且正确判断依赖范围,可以调节依赖冲突来保证只有一个版本正确引用,完成后的依赖叫已解析依赖
查看依赖列表
cmd:mvn dependency:list
查看依赖树状图
cmd:mvn dependency:tree
分析项目依赖使用情况
cmd:mvn dependency:analyze
可以查看依赖是否被使用等等
此处怀疑只能看到scope为compile而没被用到的依赖,scope为provided但实际在项目中要用到的依赖同样会显示unused dependency
5、Maven仓库
5.1、仓库路径
路径的构建规则与步骤为:
1、groupId的.替换成/
2、后面加上artifactId,同样把.替换成/
3、加上version,后面带上/
4、加上artifactId,分隔符,version,如果有classifier则加上
5、最后加上扩展名
举个例子:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
在仓库中的路径就是:org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar
http://central.maven.org/maven2/org/apache/commons/commons-lang3/3.1/commons-lang3-3.1.jar
5.2、仓库分类
仓库分类如下:
- 本地仓库
- 远程仓库
- 中央仓库
- 私服
- 其它远程仓库
maven在寻找依赖时,首先在本地仓库查找对应的依赖,如果没有则会从远程仓库查找,如果没有就会报错,其他的远程仓库有JBoss库、Java.net库、阿里云库等等
5.2.1、本地仓库
安装好Maven后不会有本地仓库,只有在执行了第一条命令后才会生成本地仓库
1、本地仓库的路径一般在系统的用户目录下
Windows: 系统盘符:\Users 系 统 盘 符 : \Users {用户名}\.m2\repository
Linux:/home/${用户名}/.m2/repository,linux中.开头的文件夹是隐藏的,可以用ls -a看到
2、设置本地仓库的目录:在settings.xml下的localRepository节点下设置
<localRepository>D:\maven\repository\</localRepository>
3、本地仓库中的构件的来源
- 远程仓库下载
- 本地install
5.2.2、远程仓库
1、当要用到某个构件时,Maven先从本地仓库找,找不到的话才会从远程仓库去寻找,本地仓库只有一个,但是远程仓库可以配置多个
2、maven的默认远程仓库地址可以在lib\maven-model-builder-3.0.jar中的pom-4.0.0.xml中看到,如下
<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>
3、私服:私服是架设在局域网的远程仓库,用于代理Internet上的远程仓库供局域网用户使用,当Maven要下载构件,先从私服请求,如果没有,那么再从远程仓库下载缓存到私服,然后为局域网的用户提供服务,私服具有以下好处:
- 节省外网带宽
- 加速Maven的构建
- 部署第三方构件,因为有的构件不一定能从远程仓库下载到
- 提高稳定性、增强控制(如nexus有权限控制)
- 减小中央仓库的负荷
5.2.3、远程仓库的配置
在项目中的pom.xml中可以配置远程仓库
<project>
...
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<release>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</release>
<snapshots>
<enabled>false</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</snapshots>
<layout>default</layout>
</repository>
</repositories>
...
</project>
Maven默认的仓库id为central,如果其他配置了id为central的仓库,那么就会覆盖Maven默认的配置
release和snapshot控制Maven可以是否下载正式版或者快照版本的构件
release和snapshot中还有updatePolicy和checksumPolicy两个属性
- updatePolicy:maven检查仓库的更新的频率,默认是daily、其他的选项包括never、always(每次构建都检查)、interval:X (每X分钟检查一次)
- checksumPolicy:当maven把构件部署到仓库时,会同时部署校验和文件,当checksumPolicy的值为warn时,Maven在每次构建时会输出警告信息,当为fail时校验和检查失败构建就会失败,ignore那么Maven不会检查校验和
layout为default时表示布局为Maven2/3的,不是1的布局
5.2.4、远程仓库的认证
有的仓库为了安全考虑是需要用户名和密码认证才能访问的,这就需要配置settings.xml
在servers节点下可以配置server属性,如下
<settings>
...
<servers>
<server>
<id>my-repo</id>
<username>username</username>
<password>password</password>
</server>
</servers>
...
</settings>
这里的id是repository节点中需要认证的id,这两个id把这两个配置关联起来