微服务之短信验证服务配置完后junit单元测试短信发送失败

总之岁月漫长,然而值得等待。

主要是版本冲突问题,具体报错与解决方法如下:

报错前:
启动失败

短信服务测试报错:

解决后:
启动成功

短信服务测试发送成功:

在使用 SpringBoot 开发时,我们经常会引入各种依赖以满足功能需求。然而,依赖版本不一致的问题可能会导致一些复杂的错误。最近在项目中,我遇到了一个典型的 NoClassDefFoundError 问题,经过排查发现其根本原因是依赖版本冲突。

一、问题描述

bash 复制代码
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2024-11-29 00:53:51.262  INFO 19140 --- [           main] c.a.alicloud.oss.OssApplicationListener  : 0 OSSClients will be shutdown soon
2024-11-29 00:53:51.278 ERROR 19140 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'OSSController': Unsatisfied dependency expressed through field 'ossClient'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ossClient' defined in class path resource [com/alibaba/alicloud/context/oss/OssContextAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.aliyun.oss.OSS]: Factory method 'ossClient' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/http/ssl/SSLContextBuilder
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:659) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.12.jar:5.3.12]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.12.jar:5.3.12]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.12.jar:5.3.12]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.12.jar:2.4.12]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:771) [spring-boot-2.4.12.jar:2.4.12]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:763) [spring-boot-2.4.12.jar:2.4.12]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438) [spring-boot-2.4.12.jar:2.4.12]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) [spring-boot-2.4.12.jar:2.4.12]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) [spring-boot-2.4.12.jar:2.4.12]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1318) [spring-boot-2.4.12.jar:2.4.12]
	at com.chhei.mall.third.MallThirdPartyApplication.main(MallThirdPartyApplication.java:12) [classes/:na]
bash 复制代码
Caused by: java.lang.NoClassDefFoundError: org/apache/http/ssl/SSLContextBuilder

详细堆栈信息提示 SSLContextBuilder 类无法被加载,而该类属于 Apache 的 httpclient 包。在分析日志后,定位到问题是阿里云 OSS 客户端(com.aliyun.oss.OSS)在初始化时无法正确加载 org.apache.http.ssl.SSLContextBuilder 类。

二、问题分析

1.定位问题依赖 报错中提到的 SSLContextBuilder 位于 org.apache.httpcomponents 的 httpclient 包中。通过查看 Maven 仓库可知,它需要以下两个核心依赖:

httpclient
httpcore

2.版本冲突 项目中直接或间接引入了多个版本的 httpcore,分别是:
通用工具类:

bash 复制代码
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.4.14</version>
</dependency>

第三方服务类:

bash 复制代码
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2.1</version>
</dependency>

这两个依赖版本要统一或接近,统一完后就不报错了,具体统一可以直接改成一模一样的版本,子 类pom像父类看齐,也可以参考一下其他方法。

三、解决方案(其他)

排除冲突依赖 对于引入旧版本 httpcore 的依赖,通过排除方式在子类pom文件中移除冲突版本:

bash 复制代码
<dependency>
    <groupId>某依赖的groupId</groupId>
    <artifactId>某依赖的artifactId</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
        </exclusion>
    </exclusions>
</dependency>

再引入自己独立的版本:

bash 复制代码
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2.1</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.2.1</version>
</dependency>

版本不要相差太大一般不会有什么问题。

最后终端进入对应的第三方模块输入:

bash 复制代码
mvn clean install
相关推荐
pan3035074798 小时前
GRPC详解
微服务·grpc
千里镜宵烛8 小时前
深入 Lua 元表与元方法
junit
喵个咪9 小时前
开箱即用的GO后台管理系统 Kratos Admin - 站内信
后端·微服务·go
安冬的码畜日常12 小时前
【JUnit实战3_27】第十六章:用 JUnit 测试 Spring 应用:通过实战案例深入理解 IoC 原理
spring·观察者模式·设计模式·单元测试·ioc·依赖注入·junit5
敲代码的嘎仔14 小时前
JavaWeb零基础学习Day6——JDBC
java·开发语言·sql·学习·spring·单元测试·maven
陈果然DeepVersion15 小时前
Java大厂面试真题:Spring Boot+微服务+AI智能客服三轮技术拷问实录(四)
spring boot·redis·微服务·kafka·spring security·智能客服·java面试
二宝15217 小时前
黑马商城day8-ES01
分布式·微服务·架构
安冬的码畜日常18 小时前
【JUnit实战3_28】第十七章:用 JUnit 5 实测 SpringBoot 项目
spring boot·功能测试·测试工具·设计模式·单元测试·junit5
l1t18 小时前
luadbi和luasql两种lua duckdb驱动的性能对比
开发语言·单元测试·lua·c·csv·duckdb
陈果然DeepVersion18 小时前
Java大厂面试真题:Spring Boot+Kafka+AI智能客服场景全流程解析(七)
java·人工智能·spring boot·微服务·kafka·面试题·rag