外部接口调用失败重试

外部接口调用失败重试文章目录 toc 第三方接口调用失败重试规则代码 MyRetry MyRetryFacto MyRetryTempl ResponseResu ThirdCallSer ThirdCallSer Tester 结果总结第三方接口调用失败重试规则第三方接口调用失败后 相隔 3 秒后后重试 若再次失败则相隔 5 秒重试 后续不再重试 代码 MyRetry Target ElementType METHOD Retention Retenti

第三方接口调用失败重试

规则

  1. 第三方接口调用失败后,相隔3秒后后重试;
  2. 若再次失败则相隔5秒重试,后续不再重试。

代码

@MyRetry
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyRetry { 
    int retryTimes() default 0; int[] retrySecond() default { 
   }; } 
MyRetryFactory
public class MyRetryFactory { 
    public static <T> T getRetryServiceProxy(T realObj) { 
    Class<?>[] realIntfs = realObj.getClass().getInterfaces(); Object proxyInstance = Proxy.newProxyInstance(MyRetryFactory.class.getClassLoader(), realIntfs, new InvocationHandler() { 
    @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
    // 接口方法上是否有@MyRetry if (method.isAnnotationPresent(MyRetry.class)) { 
    MyRetry myRetry = method.getDeclaredAnnotation(MyRetry.class); int retryTimes = myRetry.retryTimes(); int[] retrySeconds = myRetry.retrySecond(); MyRetryTemplate myRetryTemplate = new MyRetryTemplate() { 
    @Override public Object retry() throws Exception { 
    Object obj = method.invoke(realObj, args); if (obj instanceof ResponseResult) { 
    // 网络异常,第三方接口也会返回结果,判断code是否等于0,决定是否重试 ResponseResult responseResult = (ResponseResult) obj; if (responseResult == null || (!"0".equals(responseResult.getCode()))) { 
    if (responseResult == null) { 
    throw new RuntimeException("接口返回对象为空"); } else { 
    throw new RuntimeException(responseResult.getMsg()); } } } return obj; } }.setRetryTimes(retryTimes).setRetrySeconds(retrySeconds); // 先执行方法一次,再异步重试 try { 
    return myRetryTemplate.executeOnce(); } catch(Exception e) { 
    myRetryTemplate.executeAsync(); } return null; } else { 
    return method.invoke(realObj, args); } }; }); return (T) proxyInstance; } } 
MyRetryTemplate
public abstract class MyRetryTemplate { 
    private int retryTimes = 0; private int[] retrySeconds = { 
   }; public abstract Object retry() throws Exception; public Object executeOnce() throws Exception { 
    System.out.println("第一次执行..."); return retry(); } public Object execute() { 
    System.out.println("重试" + retryTimes + "次-分别相隔" + Arrays.toString(retrySeconds) + "秒"); for (int i = 0; i < retryTimes; i++) { 
    try { 
    System.out.println(retrySeconds[i] + "s后准备第[" + (i + 1) + "]次重试!"); Thread.sleep(1000 * retrySeconds[i]); return retry(); } catch (Exception e) { 
    System.out.println("重试失败:" + e); } } return null; } public void executeAsync() { 
    Thread thread = new Thread(new Runnable() { 
    @Override public void run() { 
    execute(); } }); thread.start(); } public MyRetryTemplate setRetryTimes(int retryTimes) { 
    this.retryTimes = retryTimes; return this; } public MyRetryTemplate setRetrySeconds(int[] retrySeconds) { 
    this.retrySeconds = retrySeconds; return this; } } 
ResponseResult
private String code; private String msg; // 省略getter/setter方法 
ThirdCallService
@MyRetry(retryTimes = 2, retrySecond = { 
   3, 5}) ResponseResult push(); 
ThirdCallServiceImpl
@Override public ResponseResult push() { 
    System.out.println("push()"); ResponseResult responseResult = new ResponseResult(); responseResult.setCode("-1"); responseResult.setMsg("连接超时,网络异常"); return responseResult; } 
Tester
ThirdCallService thirdCallService = new ThirdCallServiceImpl(); ThirdCallService thirdCallServiceProxy = MyRetryFactory.getRetryServiceProxy(thirdCallService); thirdCallServiceProxy.push(); System.out.println("============================="); 
结果
第一次执行... push() ============================= 重试2-分别相隔[3, 5]3s后准备第[1]次重试! push() 重试失败:java.lang.RuntimeException: 连接超时,网络异常 5s后准备第[2]次重试! push() 重试失败:java.lang.RuntimeException: 连接超时,网络异常 

总结

1. 符合模板方法模式。因为要重试几次,所以需要循环,循环总体逻辑一致,但是要调用的外部接口有很多。 2. 第一次正常调用接口返回结果,失败重试n次采用异步调用。 3. 采用JDK的动态代理。调用每个外部接口时,统一交由代理类实现总体重试规则代码。 4. 接口标注注解,来区分外部接口是否需要重试。 代理类可依照该注解,分别执行需要重试和不需要重试的逻辑,做到统一区分。 5. 外部接口一般异常(如网络异常)返回的对象也会有值(code,msg),code不为成功代号需要纳入重试机制。 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227906.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午8:15
下一篇 2026年3月16日 下午8:15


相关推荐

  • centos7.6开放端口命令_查看端口有没有开放

    centos7.6开放端口命令_查看端口有没有开放概要最近在docker下搭建MySQL和Redis环境,远程linux主机内部网络都走通了,但是就是外网无法连接远程服务器的MySQL和Redis。经过一番查找和学习,终于找到了问题,不仅远程服务器上docker要做好内部和外部端口的映射,关键还要对对外开放的端口添加到防火墙中。内容介绍的逻辑是:本篇文章先记录Centos7下查看防火墙状态和网络状态命令;下一篇将介绍通过docker…

    2026年4月14日
    9
  • 使用Androidkiller或APKIDE编译APK文件时出现libpng error: Not a PNG file的错误

    使用Androidkiller或APKIDE编译APK文件时出现libpng error: Not a PNG file的错误 使用Androidkiller或APKIDE编译APK文件时出现提示:&gt;W:libpngerror:NotaPNGfile&gt;W:ERROR:FailureprocessingPNGimageD:\xin\AndroidKiller_v1.3.12018\projects\CFF_100\Project\res\mipmap-xxhdpi-v4\ic_…

    2025年7月30日
    8
  • 如何理解css中的float

    最近一段时间一直在为一个即将上线的新站进行一些前端开发。自然,对CSS的使用是必不可少的了。我们在CSS中很多时候会用到浮动来布局。常见的有float:left或者float:right。简单点来说,

    2021年12月20日
    56
  • matlab中的colorbar用法(显示色阶的颜色栏)

    matlab中的colorbar用法(显示色阶的颜色栏)原文matlab画平面分布图时colorbar的设置是非常重要的,好的colorbar不仅使图像更美观,而且能够使人更容易捕捉图上传递的信息。用过matlab的同学都知道matlab默认的colormap是jet,也就是你画完图后输入“colorbar”它所显示出来的颜色。此外,matlab还自带了很多colormap,如hsv,autumn,bone,colorcube等等。我们直接…

    2022年5月31日
    357
  • EJB学习纪要

    EJB学习纪要为什么会突然要看看EJB这个老古董?前段时间准备再看看Spring的东西,当然就免不了要看一下Spring作者那本导致Spring模型的大作。其中说到Spring是在批判EJB的背景下产生的。所以,就得看看EJB这玩意儿到底搞了什么东西,粗略浏览了下目录,哗!EJB2太复杂了,算了,先从后面简化过了的EJB3看起吧,完了再反过来看看2是个什么样子。这回答真够曲折的,都快忘了当初的想法了,…

    2026年4月17日
    4
  • TCP与UDP的区别

    TCP与UDP的区别一 前言 TCP IP 中有两个具有代表性的传输层协议 分别是 TCP 和 UDP 二 TCP IP 网络模型计算机与网络设备要相互通信 双方就必须基于相同的方法 比如 如何探测到通信目标 由哪一边先发起通信 使用哪种语言进行通信 怎样结束通信等规则都需要事先确定 不同的硬件 操作系统之间的通信 所有的这一切都需要一种规则 而我们就把这种规则称为协议 protocol TCP IP 是互联网相关的各类协议族的总称 比如 TCP UDP IP FT

    2026年3月17日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号