一,相关概念
1,Maven坐标
Maven定义了这样一组规则:世界上任何一个构件都可以使用Maven坐标唯一标识,Maven坐标元素包括groupId、artifactId、version、packaging、classifier,现在只要我们提供正确的元素坐标,Maven就能找到对应的构件。至于去哪里下载,Maven本身内置了一个中央仓库的地址"http://repo1.maven.org/maven2",该中央仓库包含了世界上绝大部分流行的开源项目构件,Mavne会在需要的时候去那里下载,当然也可以配置自己的中央仓库地址,去自己的中央仓库下载构件。
2,传递性依赖
比如A项目依赖了spring-core,spring-core又依赖了commons-codec和commons-logging,那么commons-codec和commons-logging就是A项目的一个传递性依赖。有了传递性依赖机制,在使用spring-core的时候就不用去考虑它依赖了什么,也不用担心引入多余的依赖,Maven会解析各个直接依赖的POM,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中去。
当依赖发生冲突时会有依赖调解,依赖调解主要有两点原则:段路径优先和第一声明者优先
1、A->B->C->X(1.0),A->D->X(2.0),此时两条依赖路径上有两个版本的X,此时遵循路径最近者优先,因此X(2.0)将被解析使用
2、A->B->Y(1.0),A->C->Y(2.0),Y(1.0)和Y(2.0)的依赖长度是一样的,从Maven2.0.9开始,此时遵循第一声明者优先,即顺序最靠前的那个依赖优先
3,排除依赖
传递性依赖会给项目隐式地引入很多依赖,这极大地简化了项目依赖的管理,但是有时候这种特性也会带来问题。比如有种情况:
当前项目依赖A,A由于某些原因依赖了另外一个类库的SNAPSHOT版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,二SNAPSHOT的不稳定性将直接影响到当前的项目,此时就需要排除该SNAPSHOT,并且在当前项目中声明该类库的某个正式发布的版本
<dependency>
<groupId>com.alibaba.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>3.2.7</version>
<exclusions>
<exclusion>
<groupId>apache-lang</groupId>
<artifactId>commons-lang</artifactId>
</exclusion>
</exclusions>
</dependency>
这里引入了rocketmq的依赖,但是不想依赖rocketmq里面的apache-lang,而想要自己引入依赖,所以就把apache-lang给排除了。
这里需要注意的是,声明exclusion的时候只需要groupId和artifactId即可,而不需要version元素,这是因为只需要groupId和artifactId就能唯一定位依赖图中的某个依赖。换句话说,Maven解析后的依赖中,不可能出现groupId和artifactId相同,但是version不同的两个依赖。
二,settings.xml设置
settings.xml里面是Maven的基本配置,元素比较多,逐一看一下
1、proxy
proxy表示Maven的代理,看一下写法:
<proxies>
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
</proxies>
需要proxy是因为很多时候你所在的公司基于安全因素考虑,要求你使用通过安全认证的代理访问因特网。这种情况下,就需要为Maven配置HTTP代理,才能让它正常访问外部仓库,以下载所需要的资源。proxies下可以配置多个proxy元素,如果声明了多个proxy元素,则默认情况下第一个被激活的proxy会生效。active为true表示激活该代理,protocol表示使用的代理协议,当然最重要的是指定正确的主机名(host)和端口(port),如果代理服务器需要认证则配置username和password,nonProxyHost元素表示指定哪些主机名不需要代理,可以用"|"分隔多个主机名,也支持通配符"*"。
2、repository
repository表示Maven的中央仓库,因为尽管默认的远程仓库中的构件非常庞大,但是总归会有不满足我们需求的时候,这时候就要用到别的中央仓库了。看一下写法:
<repository>
<id>public</id>
<name>local private nexus</name>
<url>http://192.168.1.6:8081/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
可以声明多个repository。id必须是唯一的,尤其注意,Maven自带的中央仓库使用的id为central,如果其他仓库声明也用该id,就会覆盖中央仓库的配置。releases和snapshots比较重要,前者表示开启仓库的发布版本下载支持,后者表示关闭仓库的快照版本下载支持,这样一来,Maven就会去仓库下载发布版本的构件而不会下载快照版本的构件了。
3、server
大部分远程仓库无须认证就可以访问,但是有时候处于安全方面的因素考虑,需要提供认证信息才能访问一些远程仓库,处于安全考虑,认证信息一般只放在settings.xml中,server就是认证元素。看一下配置:
<server>
<id>nexus-releases</id>
<username>deployment</username>
<password>deployment</password>
</server>
这里的关键是id,这个id必须与需要认证的repository元素的id完全一致才行,换句话说,正式这个id将认证信息和仓库配置联系在了一起。
4、mirror
如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为仓库X是仓库Y的一个镜像(mirror),换句话说,任何一个可以从Y中获取到的构件够可以从X中获取到。举个例子,"http://maven.net.cn/content/groups/public/"是中央仓库"http://repo1.maven.org/maven2/"在中国的镜像,由于地理位置的因素,该镜像往往能够提供比中央仓库更快的服务,这就是为什么要使用mirror的原因。
看一下mirror的配置:
<mirror>
<id>nexus</id>
<name>internal nexus repository</name>
<url>http://192.168.1.6:8081/nexus/content/groups/public</url>
<mirrorOf>*</mirrorOf>
</mirror>
该例子中,mirrof为*,表示该配置为所有中央仓库的镜像,任何对于中央仓库的请求都会转至该镜像。另外三个元素id、name、url与一般仓库配置无异,表示该镜像仓库的唯一标识符、名称以及地址。类似的,如果该镜像需要认证,也可以基于该id配置仓库认证。
5,include与exclude及其filter的使用
Maven resource中的<include>与<exclude>用于包含或排除某一文件目录下的文件是否是工程资源的。若<include>与<exclude>划定的范围存在冲突,则以<include>配置为准。
使用include可以规定指定路径下的xml包括properties文件在编译期,将文件指定的@profiles.active@替换掉。
例如:XXX.properties中我们使用@profiles.active@来代表激活的偏好。那么在Maven编译时,就会将@profiles.active@替换成真正的偏好。
exclude的作用:
使用exclude可以规定指定路径下的配置文件,在编译后打包时不被放入资源路径里。
大概就是include中会被编译进jar包,exclude不会被编译进jar包。
注:
如果<include>与<exclude>划定的范围存在冲突时
并不会执行<exclude>,而是执行<include>
include和exclude里filtering总结:
filtering为true:
include:替换指定文件中@xx@表示的maven properties属性值
exclude:替换指定文件以外@xx@表示的maven properties属性值
filtering为false:
include:不替换指定文件中@xx@表示的maven properties属性值
exclude:不替换指定文件以外@xx@表示的maven properties属性值
以上<include>与<exclude>划定的范围存在冲突,则以<include>配置为准。
6,maven-shade-plugin插件
artifactSet可以是将整个jar过滤掉,filters是进行jar包中更细致的过滤行为。
Maven插件maven-shade-plugin:https://blog.csdn.net/MAIMIHO/article/details/106462976 https://my.oschina.net/u/2377110/blog/1585553
pom文件中每行详细解释:https://blog.csdn.net/qq_32506245/article/details/113061321
三,检测依赖的冗余依赖
1,使用mvn dependency:analyze来分析
会智能的分析出pom文件中设置不合理的情况,比如,分析出kafka-clients在pom文件中定义了两次:
[WARNING] 'dependencies.dependency.(groupId:artifactId:type:classifier)' must be unique: org.apache.kafka:kafka-clients:jar -> version ${kafka.version} vs 0.10.2.1 @ line 115, column 17
2,
参考链接:
pox.xml和settings.xml解析:https://www.cnblogs.com/xrq730/p/5530069.html
maven常用命令以及遇到的问题:https://blog.csdn.net/rhwaitingvous/article/details/116788390?spm=1001.2014.3001.5502
maven中include、exclude、filter的使用:https://www.jianshu.com/p/3d1075de3015