Springboot Retry组件@Recover失效问题怎么解决
发表于:2025-11-06 作者:千家信息网编辑
千家信息网最后更新 2025年11月06日,这篇文章主要介绍"Springboot Retry组件@Recover失效问题怎么解决",在日常操作中,相信很多人在Springboot Retry组件@Recover失效问题怎么解决问题上存在疑惑,
千家信息网最后更新 2025年11月06日Springboot Retry组件@Recover失效问题怎么解决
这篇文章主要介绍"Springboot Retry组件@Recover失效问题怎么解决",在日常操作中,相信很多人在Springboot Retry组件@Recover失效问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Springboot Retry组件@Recover失效问题怎么解决"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
背景
在使用springboot的retry模块时,你是否出现过@Recover注解失效的问题呢?下面我会对该问题进行复现,并且简要的说下解决方法。
问题复现
首先我们引入maven
org.springframework.retry spring-retry org.aspectj aspectjweaver 1.9.6 cn.hutool hutool-all 5.5.2 org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web
主类配置EnableRetry注解
package ai.guiji.csdn; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.retry.annotation.EnableRetry; @EnableRetry@SpringBootApplicationpublic class CsdnApplication { public static void main(String[] args) { SpringApplication.run(CsdnApplication.class, args); }}准备测试的Retry组件类代码
package ai.guiji.csdn.component; import lombok.extern.slf4j.Slf4j;import org.springframework.retry.annotation.Backoff;import org.springframework.retry.annotation.Recover;import org.springframework.retry.annotation.Retryable;import org.springframework.stereotype.Component; import java.util.function.Supplier; /** @Author 剑客阿良_ALiang @Date 2021/4/22 16:07 @Description: 重试工具 */@Slf4j@Componentpublic class RetryUtil { @Retryable( value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 5000, multiplier = 1.5)) public String retry(Supplier supplier) throws Exception { String result = null; try { result = supplier.get(); } catch (Exception exception) { log.error("异常报错:{}", exception.getMessage()); throw exception; } return result; } @Recover public void recover(Exception e) { log.error("调用超过3次异常"); }} 代码说明
1、我们可以看到retry方法会重试supplier的get结果,捕获异常并抛出异常。这里抛出后会被retry捕获并且重试。
2、maxAttempts参数为重试的最大次数。
3、backoff中的delay为两次重试之间的延迟,multiplier为重试阻尼,可以这么理解,每次重试间隔时间为上一次重试间隔时间的倍数。
4、如果3次重试均抛出异常,则进入recover方法。
编写测试代码
package ai.guiji.csdn.component; import cn.hutool.core.convert.Convert;import cn.hutool.http.HttpUtil;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest; /** @Author 剑客阿良_ALaing @Date 2021/11/30 13:08 @Description: */@SpringBootTestclass RetryUtilTest { @Autowired private RetryUtil retryUtil; @Test void retry() { try { System.out.println(Convert.toStr(retryUtil.retry(() -> HttpUtil.post("xxxx", "")), "haha")); } catch (Exception exception) { exception.printStackTrace(); } }}执行测试结果
2021-11-30 13:37:44.012 ERROR 13600 --- [ main] ai.guiji.csdn.component.RetryUtil : 异常报错:UnknownHostException: xxxx2021-11-30 13:37:49.019 ERROR 13600 --- [ main] ai.guiji.csdn.component.RetryUtil : 异常报错:UnknownHostException: xxxx2021-11-30 13:37:58.787 ERROR 13600 --- [ main] ai.guiji.csdn.component.RetryUtil : 异常报错:UnknownHostException: xxxxorg.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is cn.hutool.core.io.IORuntimeException: UnknownHostException: xxxx at org.springframework.retry.annotation.RecoverAnnotationRecoveryHandler.recover(RecoverAnnotationRecoveryHandler.java:70) at org.springframework.retry.interceptor.RetryOperationsInterceptor$ItemRecovererCallback.recover(RetryOperationsInterceptor.java:142) at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:539) at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:387) at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:225) at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:116) at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:163) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) at ai.guiji.csdn.component.RetryUtil$$EnhancerBySpringCGLIB$$d209cbc6.retry() at ai.guiji.csdn.component.RetryUtilTest.retry(RetryUtilTest.java:17) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84) at java.util.ArrayList.forEach(ArrayList.java:1257) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84) at java.util.ArrayList.forEach(ArrayList.java:1257) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)Caused by: cn.hutool.core.io.IORuntimeException: UnknownHostException: xxxx at cn.hutool.http.HttpRequest.send(HttpRequest.java:1153) at cn.hutool.http.HttpRequest.execute(HttpRequest.java:969) at cn.hutool.http.HttpRequest.execute(HttpRequest.java:940) at cn.hutool.http.HttpUtil.post(HttpUtil.java:216) at cn.hutool.http.HttpUtil.post(HttpUtil.java:197) at ai.guiji.csdn.component.RetryUtilTest.lambda$retry$0(RetryUtilTest.java:17) at ai.guiji.csdn.component.RetryUtil.retry(RetryUtil.java:22) at ai.guiji.csdn.component.RetryUtil$$FastClassBySpringCGLIB$$a565f63f.invoke( ) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) at org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:93) at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329) ... 73 moreCaused by: java.net.UnknownHostException: xxxx at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at sun.net.NetworkClient.doConnect(NetworkClient.java:180) at sun.net.www.http.HttpClient.openServer(HttpClient.java:463) at sun.net.www.http.HttpClient.openServer(HttpClient.java:558) at sun.net.www.http.HttpClient. (HttpClient.java:242) at sun.net.www.http.HttpClient.New(HttpClient.java:339) at sun.net.www.http.HttpClient.New(HttpClient.java:357) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1220) at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1156) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1050) at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:984) at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1334) at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1309) at cn.hutool.http.HttpConnection.getOutputStream(HttpConnection.java:451) at cn.hutool.http.HttpRequest.sendFormUrlEncoded(HttpRequest.java:1176) at cn.hutool.http.HttpRequest.send(HttpRequest.java:1145) ... 86 more Process finished with exit code 0
并没有进入recover方法,注解未触发。
问题解决
这里有个很容易忽视的点,就是retry方法是有返回值的,所以recover方法也必须是相同类型带返回值的方法。所以要把recover方法改一下。
package ai.guiji.csdn.component; import lombok.extern.slf4j.Slf4j;import org.springframework.retry.annotation.Backoff;import org.springframework.retry.annotation.Recover;import org.springframework.retry.annotation.Retryable;import org.springframework.stereotype.Component; import java.util.function.Supplier; /** @Author 剑客阿良_ALiang @Date 2021/4/22 16:07 @Description: 重试工具 */@Slf4j@Componentpublic class RetryUtil { @Retryable( value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 5000, multiplier = 1.5)) public String retry(Supplier supplier) throws Exception { String result = null; try { result = supplier.get(); } catch (Exception exception) { log.error("异常报错:{}", exception.getMessage()); throw exception; } return result; } @Recover public String recover(Exception e) { log.error("调用超过3次异常"); return "调用超过3次异常"; }} 重新执行测试看下结果
到此,关于"Springboot Retry组件@Recover失效问题怎么解决"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!
问题
方法
组件
学习
测试
代码
剑客
注解
结果
阿良
工具
时间
更多
帮助
实用
最大
相同
接下来
之间
倍数
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
佳豪网络安全绘画
淘客返利软件开发
rup软件开发角色
海外网络安全服务
上海软件开发私人定做
页面访问数据库 什么技术
汇丰银行软件开发有限公司
杭州专业软件开发费用是多少
大型数据库有哪些应用
质量等别建数据库
数据库用户表和管理员表
qt编写程序连接服务器
天奇扬网络技术有限公司
工控网络安全保障
网络安全的英文文献带翻译
恨意流放之路数据库
答题集福软件开发何时
软件开发人员如何接外单
seer数据库注册丁香园
超级玛丽铃声软件开发
英国生物数据库官网
网络设备服务器维护
关于网络安全教育的活动流程
张店陶瓷管理软件开发公司
大学健康网络安全书
软件开发售后有保障
python动态绘制数据库曲线
丹阳科技互联网有限公司
数据库信息上传
数据库报错列与值不匹配