接口重试和返回值处理通用编程模型

利用java8的Function函数实现接口重试和返回值处理

场景:实际项目中,我们会经常调用第三方接口,而第三方接口一般会QPS限制,也就是每秒钟的请求次数限制。

这样很容易导致服务因为请求过快而报错,为了避免这个问题,我们通常需要休眠一定时间,再进行重试。

下面代码将演示用一行代码实现接口的重试和返回值处理。


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

public class MainTest {

    public static void main(String[] args) {
        System.out.println("执行method start");
        System.out.println(JSON.toJSONString(method(1)));
        System.out.println("执行method end");
        System.out.println("执行method1 start");
        System.out.println(JSON.toJSONString(method1(2)));
        System.out.println("执行method1 end");
//        执行method start
//        休息500秒重试
//        休息500秒重试
//        {"age":18,"name":"lisi"}
//        执行method end
//        执行method1 start
//        {"age":19,"name":"zhangsan"}
//        执行method1 end
    }

    /**
     * 模拟通用结果处理和异常重试
     */
    public static Person method(Object param) {
        // 调用外部结果
        JSONObject response = getResponse();
        // 结果处理
        return handleResult(response, Person.class, (Void v) -> method(param));
    }

    /**
     * 模拟自定义结果处理和异常重试
     */
    public static Person method1(Object param) {
        // 调用外部结果
        JSONObject response = getResponse();
        // 结果处理
        return handleResult(response, Person.class, (Void v) -> method1(param), (Void v) -> {
            Person person = new Person();
            person.setAge(19);
            person.setName("zhangsan");
            return person;
        });
    }

    public static JSONObject getResponse() {
        boolean isSuccess = new Random().nextInt(2) % 2 == 1;
        if (isSuccess) {
            JSONObject res = new JSONObject();
            res.put("age", "18");
            res.put("name", "lisi");
            return res;
        } else {
            JSONObject res = new JSONObject();
            res.put("error_code", "18");
            res.put("error_message", "请求过于频繁");
            return res;
        }
    }

    /**
     * 处理结果
     * @param res
     * @param clazz
     * @param retry
     * @param <T>
     * @return
     */
    public static <T> T handleResult(JSONObject res, Class<T> clazz, Function<Void, T> retry) {
        return handleResult(res, clazz, retry, null);
    }

    /**
     * 结果处理:重试、结果类型转换
     * @param res 响应
     * @param clazz 结果对象类型
     * @param retryHandler 重试函数
     * @param customResultHandler 自定义结果特殊处理函数
     * @param <T>
     * @return
     */
    public static <T> T handleResult(JSONObject res, Class<T> clazz, Function<Void, T> retryHandler, Function<Void, T> customResultHandler) {
        String result = res.toString();
        if (result.contains("error_code")) {
            // QPS超限额,休息500秒重试
            if (res.getIntValue("error_code") == 18) {
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {}
                System.out.println("休息500秒重试");
                return retryHandler.apply(null);
            }
            throw new ServerErrorException(res.toString());
        } else {
            if (clazz.equals(res.getClass())) {
                return (T)res;
            }
            if (customResultHandler == null) {
                // 结果常规处理
                return JSON.parseObject(result, clazz);
            } else {
                // 结果自定义处理
                return customResultHandler.apply(null);
            }
        }
    }

    @Data
    public static class Person{
        /**
         * 年龄
         */
        private Integer age;

        /**
         * 名称
         */
        private String name;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值