利用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;
}
}