SpringCloud升级之路2020.0.x版-4.maven依赖回顾以及项目框架结构

本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford

我们先来回顾下 maven 依赖中一个重要原则:最短路径原则。这在之后我们的使用中会经常用到。
举一个例子,假设我们以 spring-boot-parent 作为 parent:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.9</version>
</parent>
我们想用想用 elasticsearch 作为搜索引擎,在项目中添加了依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.10.2</version>
</dependency>
写好代码,一跑,报类不存在异常:
java.lang.NoClassDefFoundError: org/elasticsearch/common/xcontent/DeprecationHandler
at com.lv.springboot.datasource.ClientUTis.main(ClientUTis.java:13)
Caused by: java.lang.ClassNotFoundException: org.elasticsearch.common.xcontent.DeprecationHandler
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
看下依赖mvn dependency:tree,发现依赖的elasticsearch版本是:
org.elasticsearch.client:elasticsearch-rest-high-level-client:7.0.1
|--org.elasticsearch:elasticsearch:5.6.16
|--org.elasticsearch.client:elasticsearch-rest-client:7.0.1
|--org.elasticsearch.plugin:parent-join-client:7.0.1
|--org.elasticsearch.plugin:aggs-matrix-stats-client:7.0.1
|--org.elasticsearch.plugin:rank-eval-client:7.0.1
|--org.elasticsearch.plugin:lang-mustache-client:7.0.1
可能读者会感觉很奇怪,明明指定了elasticsearch的依赖了啊,而且是项目的根 pom,依赖不是最短路径原则么?不应该以这个依赖为准么?
仔细分析,原来 SpringBoot的DependencyManagement 中,org.elasticsearch:elasticsearch已经被包含了(以下为节选):
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.9.RELEASE</version>
<properties>
<elasticsearch.version>5.6.16</elasticsearch.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
spring-boot 其实已经考虑到用户可能要换版本了,所以将版本放入了 <properties/>,properties 也具有最短路径原则,所以可以通过在你的项目根 pom 中的 properties 增加相同 key 修改版本:
<properties>
<elasticsearch.version>7.10.2</elasticsearch.version>
</properties>
所有可以这么替换的属性, spring-boot 官方文档已经列出了,参考官方文档附录:Version Properties
也可以通过 dependencyManagement 的最短路径原则,通过在你的项目根 pom 中的增加想修改依赖的 dependencyManagement 即可:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.10.2</version>
</dependency>
</dependencies>
</dependencyManagement>
最后,可以记住下面的原则,就知道项目的依赖到底是哪个版本啦:
Maven依赖可以分为如下几部分:
- 直接依赖,就是本项目 dependencies 部分的依赖
- 间接依赖,就是本项目 dependencies 部分的依赖所包含的依赖
- 依赖管理,就是本项目 dependency management 里面的依赖
- parent 的直接依赖
- parent 的间接依赖
- parent 的依赖管理
- bom 的直接依赖(一般没有)
- bom 的间接依赖(一般没有)
- bom 的依赖管理
可以这么理解依赖:
- 首先,将 parent 的直接依赖,间接依赖,还有依赖管理,插入本项目,放入本项目的直接依赖,间接依赖还有依赖管理之前
- 对于直接依赖,如果有 version,那么就依次放入 DependencyMap 中。如果没有 version,则从依赖管理中查出来 version,之后放入 DependencyMap 中。key 为依赖的 groupId + artifactId,value为version,后放入的会把之前放入的相同 key 的 value 替换
- 对于每个依赖,各自按照 1,2 加载自己的 pom 文件,但是如果第一步中的本项目 dependency management 中有依赖的版本,使用本项目 dependency management的依赖版本,生成 TransitiveDependencyMap,这里面就包含了所有的间接依赖。
- 所有间接依赖的 TransitiveDependencyMap, 对于项目的 DependencyMap 里面没有的 key,依次放入项目的 DependencyMap
- 如果 TransitiveDependencyMap 里面还有间接依赖,那么递归执行3, 4。
由于是先放入本项目的 DependencyMap,再去递归 TransitiveDependencyMap,这就解释了 maven 依赖的最短路径原则。
Bom 的效果基本和 Parent 一样,只是一般限制中,Bom 只有 dependencyManagement 没有 dependencies

如下图所示,我们会抽象出如下几个依赖:

- 所有项目的 parent:以某版本 Spring Boot 作为 parent,管理 Spring Cloud 依赖,并且包括一些公共依赖,还有单元测试依赖。如果以后我们想修改 Spring Boot 或者 Spring Cloud 版本,就在这里修改。并且,指定了所有项目编译配置。
- Spring Framework Common:所有使用了 Spring 或者 Spring Boot 的公共依赖,一般我们编写 starter,或者编写一些工具包,不需要 Spring Cloud 的特性,就会添加这个依赖。
- Spring Cloud Common:添加了 Spring Framework Common 的依赖。我们的微服务分为主要基于 spring-webmvc 的同步微服务项目以及主要基于 spring-webflux 的异步微服务项目,其中有一些公共的依赖和代码,就放在了这个项目中。
- Spring Cloud WebMVC:添加了 Spring Cloud Common 的依赖。基于 spring-webmvc 的同步微服务项目需要添加的核心依赖。
- Spring Cloud WebFlux:添加了 Spring Cloud Common 的依赖。基于 spring-webflux 的异步微服务项目需要添加的核心依赖。
我们在微服务项目中主要使用的依赖为:
- 对于纯工具包,只使用了 Spring 与 Spring Boot 的特性的,添加 Spring Framework Common 的依赖。
- 对于基于 spring-webmvc 的同步微服务项目,添加 Spring Cloud WebMVC 的依赖。
- 对于基于 spring-webflux 的异步微服务项目,添加 Spring Cloud WebFlux 的依赖。

本小节我们回顾了并深入理解了 maven 依赖最短路径原则,然后给出了我们项目框架的结构,主要对外提供了三种依赖:只使用了 Spring 与 Spring Boot 的特性的依赖,对于基于 spring-webmvc 的同步微服务项目的依赖以及对于基于 spring-webflux 的异步微服务项目的依赖。下一节我们将对这些项目模块的 pom 文件进行详细分析。
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:

SpringCloud升级之路2020.0.x版-4.maven依赖回顾以及项目框架结构的更多相关文章
- SpringCloud升级之路2020.0.x版-1.背景
本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~ Spring ...
- SpringCloud升级之路2020.0.x版-41. SpringCloudGateway 基本流程讲解(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 接下来,将进入我们升级之路的又一大模块,即网关模块.网关模块我们废弃了已经进入维护状态的 ...
- SpringCloud升级之路2020.0.x版-6.微服务特性相关的依赖说明
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford spring-cl ...
- SpringCloud升级之路2020.0.x版-10.使用Log4j2以及一些核心配置
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Log4 ...
- SpringCloud升级之路2020.0.x版-43.为何 SpringCloudGateway 中会有链路信息丢失
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在开始编写我们自己的日志 Filter 之前,还有一个问题我想在这里和大家分享,即在 Sp ...
- SpringCloud升级之路2020.0.x版-5.所有项目的parent与spring-framework-common说明
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 源代码文件:htt ...
- SpringCloud升级之路2020.0.x版-29.Spring Cloud OpenFeign 的解析(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在使用云原生的很多微服务中,比较小规模的可能直接依靠云服务中的负载均衡器进行内部域名与服务 ...
- SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面一节,我们利用 resilience4j 粘合了 OpenFeign 实现了断路器. ...
- SpringCloud升级之路2020.0.x版-2.微服务框架需要考虑的问题
本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~ 上图中演示了一 ...
随机推荐
- 教你用python搭建一个「生活常识解答」机器人
今天教大家如何用Python爬虫去搭建一个「生活常识解答」机器人. 思路:这个机器人主要是依托于"阿里达摩院发布的语言模型PLUG",通过爬虫的方式,发送post请求(提问),然后 ...
- gRPC入门—golang实现
1.RPC 1.1 什么是RPC RPC(Remote Procedure Call),即远程过程调用,过程就是方法,简单来说,它就是一种能够像调用本地方法一样调用远程计算机进程中的方法的技术,在这种 ...
- R的基本使用
一.R的安装 1.进入R的官网,https://cran.r-project.org/ 2.下载对应的版 Downloaad R for Windows > base > Download ...
- Redisson 分布式锁源码 01:可重入锁加锁
前言 相信小伙伴都是使用分布式服务,那一定绕不开分布式服务中数据并发更新问题! 单系统很容易想到 Java 的各种锁,像 synchronize.ReentrantLock 等等等,那分布式系统如何处 ...
- Android系统Bitmap内存分配原理与优化
一.前言 笔者最近致力于vivo游戏中心稳定性维护,在分析线上异常时,发现有相当一部分是由OutOfMemory引起.谈及OOM,我们一般都会想到内存泄漏,其实,往往还有另外一个因素--图片,如果对图 ...
- 双向链表(DoubleLinkList)
双向链表 有关链表的知识可以点击我上篇文章这里就不再赘述LinkedList 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个 ...
- 6、基本数据类型(list)
6.1.列表: 1.li = [1, 12, 9, "age", ["孙子涵", ["19", 10], "张涵予"], ...
- [JLOI2011]飞行路线题解
题目描述 Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的 ...
- php laravel5.5使用rabbitmq消息队列
1.安装rabbitmq 2.安装amqp扩展 3.在Laravel中配置 Rabbitmq 我是Laravel5.5,按照文档上说我只能用6版本 composer require vladimir- ...
- ROS2学习之旅(2)——配置ROS2环境
目录 1.source一下setup文件 2.自动source 3.自动进入工作区(不常用) 4.检查环境变量是否设置成功 5.总结 ROS2依赖于使用shell(终端)环境组合工作空间的概念.工作空 ...