- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章SpringBoot @Retryable注解方式由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
背景 。
在调用第三方接口或者使用MQ时,会出现网络抖动,连接超时等网络异常,所以需要重试。为了使处理更加健壮并且不太容易出现故障,后续的尝试操作,有时候会帮助失败的操作最后执行成功。一般情况下,需要我们自行实现重试机制,一般是在业务代码中加入一层循环,如果失败后,再尝试重试,但是这样实现并不优雅。在SpringBoot中,已经实现了相关的能力,通过@Retryable注解可以实现我们想要的结果.
@Retryable 。
首先来看一下Spring官方文档的解释:
@Retryable注解可以注解于方法上,来实现方法的重试机制.
POM依赖 。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>
使用实例 。
SpringBoot retry的机制比较简单,只需要两个注解即可实现.
启动类 。
@SpringBootApplication@EnableRetrypublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
在启动类上,需要加入@EnableRetry注解,来开启重试机制.
Service类 。
前面提到过,@Retryable是基于方法级别的,因此在Service中,需要在你希望重试的方法上,增加重试注解.
@Service@Slf4jpublic class DoRetryService { @Retryable(value = Exception.class, maxAttempts = 4, backoff = @Backoff(delay = 2000L, multiplier = 1.5)) public boolean doRetry(boolean isRetry) throws Exception { log.info("开始通知下游系统"); log.info("通知下游系统"); if (isRetry) { throw new RuntimeException("通知下游系统异常"); } return true; }}
来简单解释一下注解中几个参数的含义:
名称 | 含义 |
---|---|
interceptor | Retry interceptor bean name to be applied for retryable method. |
value | Exception types that are retryable. Synonym for includes(). Defaults to empty (and if excludes is also empty all exceptions are retried). |
include | Exception types that are retryable. Defaults to empty (and if excludes is also empty all exceptions are retried). |
exclude | Exception types that are not retryable. Defaults to empty (and if includes is also empty all exceptions are retried). |
label | A unique label for statistics reporting. If not provided the caller may choose to ignore it, or provide a default. |
stateful | Flag to say that the retry is stateful: i.e. exceptions are re-thrown, but the retry policy is applied with the same policy to subsequent invocations with the same arguments. If false then retryable exceptions are not re-thrown. |
maxAttempts | the maximum number of attempts (including the first failure), defaults to 3 |
maxAttemptsExpression | an expression evaluated to the maximum number of attempts (including the first failure), defaults to 3 |
backoff | Specify the backoff properties for retrying this operation. The default is a simple specification with no properties. |
exceptionExpression | Specify an expression to be evaluated after the SimpleRetryPolicy.canRetry() returns true - can be used to conditionally suppress the retry. |
listeners | Bean names of retry listeners to use instead of default ones defined in Spring context. |
上面是@Retryable的参数列表,参数较多,这里就选择几个主要的来说明一下:
interceptor:可以通过该参数,指定方法拦截器的bean名称 。
value:抛出指定异常才会重试 。
include:和value一样,默认为空,当exclude也为空时,默认所以异常 。
exclude:指定不处理的异常 。
maxAttempts:最大重试次数,默认3次 。
backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000L;multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒.
我们把上面的例子执行一下,来看看效果:
2019-12-25 11:38:02.492 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 开始通知下游系统2019-12-25 11:38:02.493 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系统2019-12-25 11:38:04.494 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 开始通知下游系统2019-12-25 11:38:04.495 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系统2019-12-25 11:38:07.496 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 开始通知下游系统2019-12-25 11:38:07.496 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系统2019-12-25 11:38:11.997 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 开始通知下游系统2019-12-25 11:38:11.997 INFO 25664 --- [ main] c.f.l.service.impl.DoRetryServiceImpl : 通知下游系统java.lang.RuntimeException: 通知下游系统异常.........
可以看到,三次之后抛出了RuntimeException的异常.
@Recover 。
当重试耗尽时,RetryOperations可以将控制传递给另一个回调,即RecoveryCallback。Spring-Retry还提供了@Recover注解,用于@Retryable重试失败后处理方法,此方法里的异常一定要是@Retryable方法里抛出的异常,否则不会调用这个方法.
@Recover 。
public boolean doRecover(Throwable e, boolean isRetry) throws ArithmeticException { log.info("全部重试失败,执行doRecover"); return false;}
对于@Recover注解的方法,需要特别注意的是:
1、方法的返回值必须与@Retryable方法一致 。
2、方法的第一个参数,必须是Throwable类型的,建议是与@Retryable配置的异常一致,其他的参数,需要与@Retryable方法的参数一致 。
/** * Annotation for a method invocation that is a recovery handler. A suitable recovery * handler has a first parameter of type Throwable (or a subtype of Throwable) and a * return value of the same type as the <code>@Retryable</code> method to recover from. * The Throwable first argument is optional (but a method without it will only be called * if no others match). Subsequent arguments are populated from the argument list of the * failed method in order. */
@Recover不生效的问题 。
在测试过程中,发现@Recover无法生效,执行时抛出异常信息:
org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.ArithmeticException: / by zero 。
at org.springframework.retry.annotation.RecoverAnnotationRecoveryHandler.recover(RecoverAnnotationRecoveryHandler.java:61) at org.springframework.retry.interceptor.RetryOperationsInterceptor$ItemRecovererCallback.recover(RetryOperationsInterceptor.java:141) at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:512) at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:351) at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:180) at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:115) at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:153) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) at com.sun.proxy.$Proxy157.doRetry(Unknown Source) 。
追踪一下异常的信息,进入到RecoverAnnotationRecoveryHandler中,找到报错的方法public T recover(Object[] args, Throwable cause),看一下其实现:
发现报错处,是因为method为空而导致的,明明我已经在需要执行的方法上注解了@Recover,为什么还会找不到方法呢?很奇怪,再来深入追踪一下:
打断点到这,发现methods列表是空的,那么methods列表是什么时候初始化的呢?继续追踪:
发现了初始化methods列表的地方,这里会扫描注解了@Recover注解的方法,将其加入到methds列表中,那么为什么没有扫描到我们注解了的方法呢?
很奇怪,为什么明明注解了@Recover,这里却没有扫描到呢?
我有点怀疑Spring扫描的部分,可能有什么问题了,回头去看看@EnableRetry是怎么说的:
终于找到问题的所在了,对于@EnableRetry中的proxyTargetClass参数,是控制是否对使用接口实现的bean开启代理类,默认的情况下,是不开启的,问题原因就是这个,我们来实验一下,把这个参数改成true:
@EnableRetry(proxyTargetClass = true) 。
再次运行,果然没有问题了.
由此得出结论,当使用接口实现的bean时,需要将EnableRetry的参数改为true,非接口的实现,可以使用默认配置,即false.
结语 。
本篇主要简单介绍了Springboot中的Retryable的使用,主要的适用场景为在调用第三方接口或者使用MQ时。由于会出现网络抖动,连接超时等网络异常.
以上这篇SpringBoot @Retryable注解方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我.
原文链接:https://blog.csdn.net/wtopps/article/details/103698635 。
最后此篇关于SpringBoot @Retryable注解方式的文章就讲到这里了,如果你想了解更多关于SpringBoot @Retryable注解方式的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
SpringBoot-Admin 服务监控 简单介绍 Spring Boot Actuator 是 Spring Boot 自带的一个功能模块, 提供了一组已经开箱即用的生产环境下常用
我想查找通过关键字匹配字段 nameEnglish 或 nameChinese 的模型列表。我花了一个多小时谷歌搜索但我做不到。请帮忙。 Springboot Mongo 入门示例 https://s
(请注意:在调查 this issue 时,我更好地发现了我在此处介绍的问题根源) 我对 Hibernate 和 SpringBoot 非常陌生。我的项目涉及一个搜索引擎,其中索引(javafx 客户
我最近有一个 Web 应用程序从 springboot 升级到 springboot 2。当我将其部署到 Tomcat 8 时,它似乎启动了,但没有完全启动。 在 localhost.2019-09-
我是 Spring boot 的新手...我在运行 Controller 时遇到问题, Description: Field todoService in com.springboot.todoCon
我有一个SpringBoot应用程序,它使用以下配置与PostgreSQL通信,通过AWS Beanstrik部署:。在我将AWS Aurora证书更新为rds-ca-ecc384-g1之前,一切都很
实在是不知道标题写什么了 可以在评论区给个建议哈哈哈哈 先用这个作为标题吧 尝试使用 国内给出的 AI 大模型做出一个 可以和 AI 对话的 网站出来 使用 智普AI 只能 在控制
一、介绍 在实际的软件系统开发过程中,由于业务的需求,在代码层面实现数据的脱敏还是远远不够的,往往还需要在数据库层面针对某些关键性的敏感信息,例如:身份证号、银行卡号、手机号、工资等信息进行加密存储
Selenium Selenium是一个用于Web应用程序自动化测试的开源工具套件。它主要用于以下目的: 浏览器自动化:Selenium能够模拟真实用户在不同浏览器(如Chrome、Fire
一、简介 在实际的项目开发过程中,经常需要用到邮件通知功能。例如,通过邮箱注册,邮箱找回密码,邮箱推送报表等等,实际的应用场景非常的多。 早期的时候,为了能实现邮件的自动发送功能,通常会使用 Ja
SpringBoot:基于redis自定义注解实现后端接口防重复提交校验 一、添加依赖 org.springframework.boot spring
SpringBoot:使用Jackson完成全局序列化配置 一、测试准备 com.fasterxml.jackson.core jackson-cor
springboot:整合rocketmq 一、简易消息操作 生产者整合mq 导入依赖 org.springframework.boot
springboot:常用注解 一、spring常用注解 包扫描+组件标注注解 @Component:泛指各种组件 @Controller、@Service、@Repository都可以称为@Comp
我们经常需要在两个系统之间进行一些数据的交互,这时候我们就需要开发数据交互接口。 一般来说,遇到比较多的接口有HTTP接口、WebService接口、FTP文件传输。今天我要来学习一下在SpringB
背景 近期项目上线,甲方要求通过安全检测才能进行验收,故针对扫描结果对系统进行了一系列的安全加固,本文对一些常见的安全问题及防护策略进行介绍,提供对应的解决方案 跨站脚本攻击 XSS常发生于论坛评论等
1.排除 Spring-boot-starter 默认的日志配置 将原本的 spring-boot-starter 改为 org.springframework.boot
springboot:解决跨域问题 一、跨域简介 URL的组成: // 协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址 http://www.baidu.com:8080/ 只要协
一、自定义Starter 的思路: 创建一个Maven工程,创建三个模块 一个模块为demo-app,一个模块为demo-module,一个模块为demo-module-springboot-star
1.pom.xml 4.0.0 org.springframework.boot spring-boot-starter-parent
我是一名优秀的程序员,十分优秀!