中文网站什么意思,wordpress电脑访问不了,高州新闻 头条 今天,wordpress资源下载页面文章目录 1 问题背景2 前言3 多处重复的重试机制代码4 优化后的代码5 进一步优化 1 问题背景 在电商场景中#xff0c;会调用很多第三方的云服务#xff0c;比如发送邮件、发起支付、发送验证码等等。由于网络存在抖动#xff0c;有时候发起调用后会拿到500的状态码#xf… 文章目录 1 问题背景2 前言3 多处重复的重试机制代码4 优化后的代码5 进一步优化 1 问题背景 在电商场景中会调用很多第三方的云服务比如发送邮件、发起支付、发送验证码等等。由于网络存在抖动有时候发起调用后会拿到500的状态码io exception等报错因此需要重新调用简称重试机制。项目中很多地方用到重试机制导致很多重复的代码因此笔者考虑使用Java8函数式接口优化该重试机制抽成一个工具类方法。 2 前言 本文的代码中可能有些类型没有给出代码不需要纠结主要了解函数式接口怎么应用即可 3 多处重复的重试机制代码 项目中多次出现的代码如下 BasicResponseString response null;int retryTimes 0;do {try {String startTimeStr DATE_TIME_FORMATTER.format(LocalDateTime.now());response restTemplate.postForString(basicRequest); // 此行代码是可变的可能是get方式请求可能是post方式String endTimeStr DATE_TIME_FORMATTER.format(LocalDateTime.now());PayReq logObject PayReq.getLogObject(payReq);log.info(XXXPay payOrder, request:{}, response:{}, startTimeStr:{}, endTimeStr:{}, retryTimes:{}, JSON.toJSONString(logObject), JSON.toJSONString(response), startTimeStr, endTimeStr, retryTimes);} finally {if (response ! null !response.getCode().equals(HttpStatus.SC_OK)) {try {Thread.sleep(500L);} catch (InterruptedException e) {e.printStackTrace();}}retryTimes;}} while (!response.getCode().equals(HttpStatus.SC_OK) retryTimes 3);分析
如上所示在这行代码response restTemplate.postForString(basicRequest);是可变的有可能是get方式提交http请求有可能是post方式。因此要把此处抽象出来交给调用者写具体实现。调用者需要拿到http响应报文那么抽象出来的接口需要有返回值。那么此处可以使用Supplier函数式接口或者自己定义一个有返回值的函数式接口也可以。
在log.info打日志这行需要打出响应报文、开始时间、结束时间、重试次数等这些都可以抽到工具类里面但是日志的内容XXXPay payOrder这些是可变的应该交由调用者写具体实现。那么我们可以定义一个函数式接口出来有入参但无返回值入参是提供给调用者使用的。
4 优化后的代码 定义一个打日志的函数式接口 /*** 打日志的函数式接口* * param T*/
FunctionalInterface
public interface LogFuncT {/*** 打日志* * param response 响应报文* param startTimeStr http调用开始时间* param endTimeStr http调用结束时间* param curTime 当前重试次数*/void log(T response, String startTimeStr, String endTimeStr, int curTime);
}Http重试工具类如下主要关注有代码注释的那两处地方即可 Slf4j
public class HttpRetryUtil {private final static DateTimeFormatter DATE_TIME_FORMATTER DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss:SSS);public static T T retryOnException(SupplierT supplier, LogFunc logFunc,int maxRetryTimes, long sleepMillis) {T result null;int retryTimes 0;do {try {String startTimeStr LocalDateTime.now().format(DATE_TIME_FORMATTER);// 交给调用者写具体实现并把值返回出去result supplier.get();String endTimeStr LocalDateTime.now().format(DATE_TIME_FORMATTER);// 交给调用者写具体实现入参供调用者使用logFunc.log(result, startTimeStr, endTimeStr, retryTimes);} catch (Exception e) {e.printStackTrace();} finally {if (result ! null !((BasicResponseString) result).getCode().equals(HttpStatus.SC_OK)) {try {Thread.sleep(sleepMillis);} catch (InterruptedException e) {e.printStackTrace();}}retryTimes;}} while (((result null) || !((BasicResponseString) result).getCode().equals(HttpStatus.SC_OK)) retryTimes maxRetryTimes);return result;}
}测试用例如下所示优化前有21行/代码见第3小节的代码其实如果不写注释不换行只需用1行就可以将这个重试机制调用起来了见下面的代码简洁多了 Slf4j
public class HttpRetryUtilTest extends AppTest {Resourceprivate HttpRestTemplate restTemplate;Testpublic void testRetry(){BasicRequest basicRequest new BasicRequest();basicRequest.setMethodUrl(https://www.google.com);BasicResponseString resp HttpRetryUtil.retryOnException(// 实现supplier函数式接口() - restTemplate.getForString(basicRequest), // 实现LogFunc函数式接口(response, startTimeStr, endTimeStr, curTime) - log.info(HttpRetryUtil retryOnException, request:{}, response:{}, startTimeStr:{}, endTimeStr:{}, times:{}, JSON.toJSONString(basicRequest), JSON.toJSONString(response), startTimeStr, endTimeStr, curTime), 3, 500L);log.info(repsonse:{}, JSON.toJSONString(resp));}
}5 进一步优化 针对那些重试次数、休眠时间可以在工具类中再定义一些默认的重试次数、默认的休眠时间然后利用Java的多态特性方法重载定义多种工具方法即可。