Springboot-Retry组件@Recover失效问题解决,2024年最新linux学习书籍

本文探讨了Springboot中使用Retry组件进行异常重试的问题,详细解析了@Retryable和@Recover注解的使用。当@Recover方法无法触发时,原因可能是重试方法的返回类型与@Recover方法不匹配。文中给出了测试代码示例,展示了如何正确配置和使用这两个注解,以便在遇到异常时执行恢复操作。同时,分享了一位开发者的职业经历和学习资源,鼓励大家不断提升自己的技术水平。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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: */

@SpringBootTest

class 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: xxxx

2021-11-30 13:37:49.019 ERROR 13600 — [ main] ai.guiji.csdn.component.RetryUtil : 异常报错:UnknownHostException: xxxx

2021-11-30 13:37:58.787 ERROR 13600 — [ main] ai.guiji.csdn.component.RetryUtil : 异常报错:UnknownHostException: xxxx

org.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 E n h a n c e r B y S p r i n g C G L I B EnhancerBySpringCGLIB EnhancerBySpringCGLIBd209cbc6.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 R e f l e c t i v e I n t e r c e p t o r C a l l . l a m b d a ReflectiveInterceptorCall.lambda ReflectiveInterceptorCall.lambdaofVoidMethod$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 F a s t C l a s s B y S p r i n g C G L I B FastClassBySpringCGLIB FastClassBySpringCGLIBa565f63f.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 more

Caused 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;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

结语

小编也是很有感触,如果一直都是在中小公司,没有接触过大型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

送给每一位想学习Java小伙伴,用来提升自己。

在这里插入图片描述

本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

型的互联网架构设计的话,只靠自己看书去提升可能一辈子都很难达到高级架构师的技术和认知高度。向厉害的人去学习是最有效减少时间摸索、精力浪费的方式。

我们选择的这个行业就一直要持续的学习,又很吃青春饭。

虽然大家可能经常见到说程序员年薪几十万,但这样的人毕竟不是大部份,要么是有名校光环,要么是在阿里华为这样的大企业。年龄一大,更有可能被裁。

送给每一位想学习Java小伙伴,用来提升自己。

[外链图片转存中…(img-gKwYo9Rq-1712810110009)]

本文到这里就结束了,喜欢的朋友可以帮忙点赞和评论一下,感谢支持!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-rIthZMza-1712810110009)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值