这个Maven依赖的问题,你敢说你没遇到过
使用Maven时如果未被妥善处理的依赖常常会引发问题令人感到不满。最近我们分享了一个关于依赖管理的问题发现很多人之前都可能遇到过。
问题背景
一个基于 Elasticsearch 的搜索系统,在起初运行正常的情况下,在某个时间段后出现服务启动时的错误信息。检查了 Git 提交记录未发现任何修改操作后仍未能解决这个问题,“看似正常的代码却隐藏着问题的地方”。
错误如下图所示,很明显的错误,经常会碰到,肯定是依赖版本的问题。

该软件项目由我自行进行了封装,并在内部采用了Elasticsearch组件。起初测试过程运行正常。然而,在某次操作后发现无法正常运行。随后检查项目依赖项列表时发现相关软件版本被更新至 6.4.3,请确保系统配置正确并重新启动服务以解决问题。因此导致系统中缺少CountRequest类而无法完成预期功能

问题原因
从目前来看似乎我的项目中存在某个地方设置了版本限制,并且这个限制涵盖了kitty-spring-cloud-starter-elasticsearch所定义的6.8.7版本。
在项目父pom中也未发现相关配置,在Spring Boot组件中发现了设置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath />
</parent>
代码解释
在 spring-boot-dependencies 中找到了 6.4.3 的配置。
<elasticsearch.version>6.4.3</elasticsearch.version>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.distribution.integ-test-zip</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>${elasticsearch.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
代码解释
我们都知道当父POM中的dependencyManagement配置了版本时,默认情况下子模块无需自行指定版本;它们会继承使用父POM的版本。因为我们没有强制配置最顶层的parent POM来明确设定各个子模块的具体依赖关系。
下图就是我们 pom 的依赖关系:

问题解决
通过项目的pom明确指定 versions,并使其具有更高的 priority than its parent pom's versions. 这是为了实现以下目标: 在 kitty-cloud-search.pom 中即可实现这一目标.
<dependency>
<groupId>com.cxytiandi</groupId>
<artifactId>kitty-spring-cloud-starter-elasticsearch</artifactId>
<exclusions>
<exclusion>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<groupId>org.elasticsearch.client</groupId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.7</version>
<exclusions>
<exclusion>
<artifactId>elasticsearch-rest-client</artifactId>
<groupId>org.elasticsearch.client</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.8.7</version>
</dependency>
代码解释
这样做能解决问题,始终感觉不是很好。
如果想要规避这个问题,则必须确保我们已经预先指定了 spring boot 的版本号以避免冲突,并且这样才能保持一致性;然而,在实际应用中仍然会遇到一些特殊情况;即使你已经在 2.1.6.RELEASE 版本中设置了 spring-boot 所使用的 es 版本为 6.4.3 来保证兼容性;但是有时候我们也会希望使用其他版本号来满足特定需求。
如果公司内部采用统一的开发框架的话,则你可以根据需要自定义 dependencies 来管理不同版本,并将 spring-boot-dependencies 的配置文件复制一份到相应位置,并修改 Elasticsearch 的 version字段设置。这样就可以在项目中方便地使用你自定义的 dependencies。
关于作者 :尹吉欢,简单的技术爱好者,《Spring Cloud 微服务-全栈技术与案例解析》, 《Spring Cloud 微服务 入门 实战与进阶》作者, 公众号 猿天地 发起人。个人微信 jihuan900 ,欢迎勾搭。
