详解SpringBoot中如何优雅地重试调用第三方API?

这篇具有很好参考价值的文章主要介绍了详解SpringBoot中如何优雅地重试调用第三方API?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

作为后端程序员,我们的日常工作就是调用一些第三方服务,将数据存入数据库,返回信息给前端。但你不能保证所有的事情一直都很顺利。像有些第三方API,偶尔会出现超时。此时,我们要重试几次,这取决于你的重试策略。

下面举一个我在日常开发中多次看到的例子:

public interface OutSource {
    List<Integer> getResult() throws TimeOutException;
}

@Service
public class OutSourceImpl implements OutSource {

    static Random random = new Random();
    @Override
    public List<Integer> getResult() {
        //mock failure
        if (random.nextInt(2) == 1)
            throw new TimeOutException();
        return List.of(1, 2, 3);
    }
}


@Slf4j
@Service
public class ManuallyRetryService {

    @Autowired
    private OutSource outSource;

    public List<Integer> getOutSourceResult(String data, int retryTimes) {
        log.info("trigger time:{}", retryTimes);

        if (retryTimes > 3) {
            return List.of();
        }

        try {
            List<Integer> lst = outSource.getResult();
            if (!CollectionUtils.isEmpty(lst)) {
                return lst;
            }

            log.error("getOutSourceResult error, data:{}", data);
        } catch (TimeOutException e) {
            log.error("getOutSourceResult timeout", e);
        }
        // 递归调用
        return getOutSourceResult(data, retryTimes + 1);
    }

}

@Slf4j
@RestController
public class RetryTestController {

    @Autowired
    private ManuallyRetryService manuallyRetryService;
    
    @GetMapping("manually")
    public String manuallyRetry() {
        List<Integer> result = manuallyRetryService.getOutSourceResult("haha", 0);
        if (!CollectionUtils.isEmpty(result)) {
            return "ok";
        }
        return "fail";
    }
}

看看上面这段代码,我认为它可以正常工作,当retryTimes达到4时,无论如何我们都会得到最终结果。但是你觉得写的好吗?优雅吗?下面我来介绍Spring中的一个组件:spring-retry,我们不妨来试一试。

Spring-Retry介绍使用

spring-retry是Spring中的提供的一个重试框架,提供了注解的方式,在不入侵原有业务逻辑代码的方式下,优雅的实现重处理功能。

安装依赖

  • 如果你的是gradle应用,引入下面的依赖
implementation 'org.springframework.boot:spring-boot-starter-aop''org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.retry:spring-retry'
  • 如果你的项目使用的是maven项目,引入下面的依赖
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

启用重试功能

添加@EnableRetry注解在入口的类上从而启用功能。

@SpringBootApplication
//看过来
@EnableRetry
public class TestSpringApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestSpringApplication.class, args);
    }

}

应用

我们以前面的为例,看看怎么使用,如下面的代码:

public interface OutSource {
    List<Integer> getResult() throws TimeOutException;
}

@Service
public class OutSourceImpl implements OutSource {

    static Random random = new Random();
    @Override
    public List<Integer> getResult() {
        //mock failure will throw an exception every time
        throw new TimeOutException();
    }
}

@Slf4j
@Service
public class RetryableService {

    @Autowired
    private OutSource outSource;

    // 看这里
    @Retryable(value = {TimeOutException.class}, maxAttempts = 3)
    public List<Integer> getOutSourceResult(String data) {
        log.info("trigger timestamp:{}", System.currentTimeMillis() / 1000);

        List<Integer> lst = outSource.getResult();
        if (!CollectionUtils.isEmpty(lst)) {
            return lst;
        }
        log.error("getOutSourceResult error, data:{}", data);

        return null;
    }

}


@Slf4j
@RestController
public class RetryTestController {

    @Autowired
    private RetryableService retryableService;

    @GetMapping("retryable")
    public String manuallyRetry2() {
        try {
            List<Integer> result = retryableService.getOutSourceResult("aaaa");
            if (!CollectionUtils.isEmpty(result)) {
                return "ok";
            }
        } catch (Exception e) {
            log.error("retryable final exception", e);
        }
        return "fail";
    }

}
  • 关键在于Service层中的实现类中添加了 @Retryable注解,实现了重试, 指定value是TimeOutException异常会进行重试,最大重试maxAttempts3次。

验证

这一次,当我们访问
http://localhost:8080/retryable时,我们将看到浏览器上的结果失败。然后在你的终端上看到:文章来源地址https://www.toymoban.com/news/detail-432782.html

INFO 66776 --- [nio-9997-exec-1] c.m.testspring.service.RetryableService  : trigger timestamp:1668236840
 INFO 66776 --- [nio-9997-exec-1] c.m.testspring.service.RetryableService  : trigger timestamp:1668236841
 INFO 66776 --- [nio-9997-exec-1] c.m.testspring.service.RetryableService  : trigger timestamp:1668236842
ERROR 66776 --- [nio-9997-exec-1] c.m.t.controller.RetryTestController     : retryable final exception

到了这里,关于详解SpringBoot中如何优雅地重试调用第三方API?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【SpringBoot系列】如何优雅地实现异步调用

    1.前言 在现代的应用程序开发中,异步调用是提高系统性能和响应能力的重要手段之一。 Spring Boot作为一个快速开发框架,提供了多种方式来实现异步调用,使得开发者能够更加优雅地处理并发和异步任务。 本文将介绍如何在Spring Boot中实现异步调用的方法和技巧,帮助开发

    2024年02月07日
    浏览(27)
  • SpringBoot案例 调用第三方接口传输数据

    最近再写调用三方接口传输数据的项目,这篇博客记录项目完成的过程,方便后续再碰到类似的项目可以快速上手 项目结构: 这里主要介绍HttpClient发送POST请求工具类和定时器的使用,mvc三层架构编码不做探究 pom.xml application-dev.yml Constast utils scheduled 该定时任务每10秒执行一

    2024年02月12日
    浏览(46)
  • 【Springboot系列】Springboot系列-调用第三方接口的五种方式汇总,代码实例

    在开发中,经常需要调用第三方接口或者其他的应用接口来完成业务需求。今天分享下Spring Boot中调用第三方接口的多种方式。 1、使用OpenFeign进行调用(推荐) 2、使用原始httpClient请求 3、使用RestTemplate方法 4、使用hutool.httputil 5、使用OkHttp3 Feign是一个声明式的Web Service客户端

    2024年02月11日
    浏览(35)
  • SpringBoot调用第三方WebService接口的两种实现方式

    WebService接口的发布通常一般都是使用WSDL(web service descriptive language)文件的样式来发布的,该文档包含了请求的参数信息,返回的结果信息,我们需要根据WSDL文档的信息来编写相关的代码进行调用WebService接口。接下来我将采用常见的两种方式调用WebService接口。 目前我需要

    2024年02月12日
    浏览(52)
  • Springboot实现上传文件,并实现调用第三方接口post请求多文件上传文件

    项目过程中,经常会有和第三方接口打交道的过程,今天实现调用第三方上传文件的接口!! 通常拿到第三方的接口文档的时候,不是第一时间先写代码,而是详细阅读接口文档。若接口需要第三方提供的基本参数,例如signkey, secrect等,也可以是其他的,查看文档里是否提

    2024年02月16日
    浏览(38)
  • Forest-声明式HTTP客户端框架-集成到SpringBoot实现调用第三方restful api并实现接口数据转换

    声明式HTTP客户端API框架,让Java发送HTTP/HTTPS请求不再难。它比OkHttp和HttpClient更高层, 是封装调用第三方restful api client接口的好帮手,是retrofit和feign之外另一个选择。 通过在接口上声明注解的方式配置HTTP请求接口。 官网: Forest   代码地址: forest: 声明式HTTP客户端API框架,让

    2024年02月04日
    浏览(100)
  • 万字长文讲解调用第三方接口,RestTemplate,urlConnection使用详解,java代码模拟postman发送请求

    业务场景 :在日常开发中,经常需要调用第三方接口,例如调用物流接口,此时需要利用urlConnection或者restTemplate模拟postman发送请求,请求支持加header ,设置content-type支持传递json;请求方式get,post,也可以需要传递文件,或者传递文件流; 下面这个例子就包含日常开发中大

    2024年02月05日
    浏览(49)
  • 互联网大厂技术-HTTP请求-Springboot整合Feign更优雅地实现Http服务调用

    目录 一、SpringBoot快速整合Feign 1.添加Pom依赖 2.启动类添加注解 3.引用Feign服务 二、为请求添加Header的3种方式 1.添加固定header 2.通过接口签名添加header 3.动态添加header 三、为请求添加超时配置 1.默认超时时间 3.超时异常 4.全局超时配置 5.为单个服务设置超时配置 四、为请求配

    2024年02月04日
    浏览(46)
  • 在yolov5的detect中我该如何调用第三方摄像头?

    要在 YOLOv5 的 detect 中调用第三方摄像头,你可以使用 OpenCV 库中的 VideoCapture 类来读取摄像头的视频流。 你可以这样做: 首先,安装 OpenCV 库。 然后,在你的代码中包含以下头文件: 接下来,创建一个 VideoCapture 对象,用于获取摄像头的视频流: 然后,打开摄像头,并检查

    2024年02月12日
    浏览(34)
  • Spring Cloud Gateway如何优雅地进行feign调用

    之前写过一篇文章,介绍微服务场景下的权限处理,方案如下: 在实践中,上面的网关选型为Spring Cloud Gateway,所以这里就存在一个问题,即网关如何调用用户服务进行鉴权的问题。 在微服务场景下,服务间的调用可以通过feign的方式,但这里的问题是,网关是reactor模式,即

    2024年02月08日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包