大白话解说maven初学者最好知道的一些事

大家好, 这里是K字的研究. 我是最近比较忙的老K.

好久没更新了, 因为最近工作比较紧. 今天礼拜五, 抽空更一篇,表示我还没弃坑. 谈谈maven.说一些我踩过坑才了解到的事.  

大白话解说maven初学者最好知道的一些事

1起因

想谈这个, 主要是因为工作中实在是发现太多人不懂maven到底怎么用的.这里不提底层原理和插件, 只谈基本的使用, 我们逐个说一下几个基本maven的使用问题.

2maven的基本工作方式

  1. 天上有个仓库
  2. 地上(电脑)有个仓库
  3. 仓库的主要内容是dependency
  4. 项目有个配方(pom.xml),里面描述了dependency
  5. 项目根据配方把dependency从天上拉到地上.

正常的使用, 知道这些就可以开始了.基本上的问题都是围绕这些点开展的.

3maven 依赖snapshot版本拉不到

这是一个常见问题, 经常会遇到别人deploy了以后, 这边拉不到的问题.deploy操作, 只表示了对方把依赖发到了天上,地上是没有的.

  • 形如0.0.1这样的版本是普通版

  • 形如0.0.1-snapshot这样的版本号, 表示这个依赖是快照版本.

快照版本的更新规则

对于快照版本的管理, maven检查更新的默认周期是1天. 如果想让maven直接去检查天上是否有更新, 需要加上 mvn -U来表示, 需要直接去检查天上的新版本.

强制更新命令行参数 -U

大白话解说maven初学者最好知道的一些事

如果不添加这个命令行参数-U 那么就会遇到死活拉不到新依赖,下班走人,第二天, 发现好了的灵异事件.

Intellij Idea 强制更新

日常使用的开发工具, 也有设置来表示每次刷新都检查是否是新版.位置在: Build->Build Tools->Maven: Always update snapshots(始终更新快照)

大白话解说maven初学者最好知道的一些事

settings.xml内的设置

当然,更新设置的默认设置也可以在settings里面改动. 在设置里       <snapshotPolicy>always</snapshotPolicy> 这个晚点提到settings再说.

4maven的依赖(dependency)包含什么

最直觉的想法, 肯定是依赖==jar,但是其实不全是:

依赖=jar+pom

比如, 我们最常用的spring-boot-starter, 引入的时候, 可能是这么写的.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.5.5</version>
</dependency>

按照这个描述, 翻开天上的仓库, 会发现, 其实有多份文件. 最核心的是这两份.

大白话解说maven初学者最好知道的一些事

这个很重要.

我们引入别人的jar包, 排除依赖等等操作,往往就是在排除随jar附赠的pom里面的垃圾内容.

dubbo之类项目的jar包api,打的合不合格, pom里面到底有啥, 就是一个很关键的参考点.

我层有幸见过一个往jar包里带了个springboot-starter-web的, 我们项目本来是没使用web的,结果因为他的包自动监听了一个8080端口,说多了都是泪.

天上的仓库有哪些

一般来说, maven有个独一无二的大仓库, 人称中央仓库. 地址是Maven Repository: Search/Browse/Explore (mvnrepository.com). maven工具的默认配置就是这个.

但是, 天有二日. 自己也可以使用nexus之类工具, 自行部署天上的仓库. 比如为了方便国内用户快速访问中央仓库, 大企业都提供了免费的镜像加速.常见的比如:

  • 阿里镜像  仓库服务 (aliyun.com)
  • 华为镜像 华为开源镜像站_软件开发服务_华为云 (huaweicloud.com)

当然,因为私有jar包的问题, 很多公司,会自己部署一个镜像在内网. 大多也是使用 nexus 工具.

5地上的仓库在哪里

maven下载下来的依赖, 其实都存在了本地.

默认位置是, 用户主目录( 就是和用户名一样的那个目录)下.m2/repository文件夹.

  • Linux用户  对应 cd ~/.m2/repository
  • windows用户,  WinKey+R,打开运行, 输入cmd,跳出来的窗口一般就定位在主目录. 继续cd .m2/repository即可.

可以改, 但是一般不推荐修改, 没必要.

6设置settings.xml怎么修改

这个随个人喜好.  但是, 我一般不推荐修改maven安装文件夹下面的settings.xml.有需要修改的话, 最好修改主目录下面的settings.xml.

maven读取配置属性是符合继承关系的.

  • 先读取.m2下面的settings.xml里的内容
  • 后读取安装目录下面的settings.xml

前面说的几个天上仓库, 最好用的是华为的. 因为别的只教你, 加上这个xml片段到settings设置. 但是华为提供了一个完整的settings.xml.

大白话解说maven初学者最好知道的一些事

当然, 别听他后半句修改conf, 直接放到主目录下.m2就可以. 从命令行进入.m2的方法是:explorer .

7maven进程杀掉以后, 某个依赖再也拉不到

这个和前面的快照问题还不太一样. 从天上往地上同步时候, 一般maven会选择加一个锁来控制这件事. 这里用的是文件锁, 是一个本地文件,就在本地仓库那个依赖旁边. 如果直接杀死进程, 可能会造成锁文件残留,有时候需要手动清理.

8文件完整性校验

有时候会见到这种形式, sha1结尾的文件.

zookeeper-3.4.9.pom
zookeeper-3.4.9.pom.sha1

其实这里面啥都没有, 就是个校验和9a86b9975bfb98cb82c74a9e45c92e183a526bf2.有些时候可以手动修改pom文件,并修改这个值来避开某些坑, 但是希望你永远用不到这个技能吧. 真心的.

9如何进行扩展

想玩儿一点点花的, 可以参考下以前写过的代码生成.

10小结

这篇的正文就到这里, 一般性的使用基础,了解上面的就差不多了. 接下来说一点点稍微有点复杂的东西.

11依赖管理

先瞎说几个概念.

pom是什么?

pom全名(project object model), 项目对象模型.

我们前面说settings就提到过, settings这样的xml是有继承关系的. pom这样的,其实也有. 你看他名字里带个object,其实就更明显了.

pom继承关系

pom的o是 object, 这里其实和Java的继承是一样的,只是用了xml来写.

Java对象不指定  extends时候, 父类都是Object.  pom不写父pom, 默认是继承 super POM.就是这货 Maven Model Builder – Super POM (apache.org) 这个就是所有pom的公共父类.

pom手动指定父pom

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
    <relativePath>../parent/pom.xml</relativePath>
  </parent>
</project>

pom聚合

写Java时候, 聚合优于继承. 写xml也是一样.

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <packaging>pom</packaging>
 
  <modules>
    <module>my-module</module>
  </modules>
</project>

这个modules的写法, 就是聚合. 和java里是很像的.

依赖关系

回顾下上面的内容,  pom 其实是一个一个节点对象,通过dependency互相关联. 如果抽象成Java结构是这样的.

class Project{
    List<Project> dependencies;

这个结构比xml容易看, 一眼能看出来, 这是一个单根的树结构.mvn 其实也有这个概念, 依赖本来就是叫依赖树的.

这个, 在intellij仓库里, 有一个maven helper插件, 用来分析这个非常好用. 强烈推荐.

大白话解说maven初学者最好知道的一些事

重复依赖

这里有个问题, 普通的树,节点都是不一样的. 但是在pom里, 有可能出现A->B-C,A-C这种情况, 两方甚至更多方都依赖C.

这种情况下, maven的处理规则的, 就近原则.

会根据依赖树的深度来计算权重, 谁出现的层级更高,更靠近根,就会被选中, 这个叫nearest definition.

  A
├── B
│ └── C
│ └── D 2.0
└── E
└── D 1.0

这种情况, 选用D 1.0, 因为他只有2层, D2.0是在第三层. 图出自maven官网文档.

如果要解决重复依赖的问题,有两个方向

  1. 排除法   让树里不存在重复节点,自然解决问题
  2. 手动强行指定

排除法

这个是最简单的思路, 把依赖的排除掉,只保留一个,<exclusions>就是做这个的.里面可以罗列上要排除内容.

有一个小技巧, 这里的排除是支持通配的. 甚至可以写成这样.除非知道自己在干什么,否则不推荐写到这么夸张.

<exclusions>
       <exclusion>
        <groupId>*</groupId>
        <artifactId>*</artifactId>
       </exclusion>
</exclusions>

强制指定 Dependency management

这是另一种思路.毕竟就近原则只是默认规则,如果手动指定, 是能盖掉这个规则的.

日常项目里经常看到的dep…m…元素,就是这个用途.

这项配置是在重复依赖里不排除的前提下, 手动指定版本号配置.版本号就会以配置为准,而不是根据最近原则了.

项目多继承问题

dependencyManagement还能解决另一个问题: 项目多继承.

Java中的类只能有一个父类. pom.xml这里也是相似的.如果想要打破这个规则, 也有变通的办法.

一般会借助dependencyManagement标签的import属性:

  • 一个做父pom
  • 一个import.

日常使用spring cloud时候, 会这么引入.

<properties>
    <spring.cloud-version>Hoxton.SR8</spring.cloud-version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring.cloud-version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这段<scope>import</scope>就是import内容. 用来解决多继承问题的.


好了, 今天就到这里. 不然12点前发不出去了. 我是一直在加班的老K. 我们回头再见.

大白话解说maven初学者最好知道的一些事


原文始发于微信公众号(K字的研究):大白话解说maven初学者最好知道的一些事

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/24828.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!