上一篇文章用实例分析了使用spring-retry实现的业务重试逻辑,本篇将使用另一重试工具库guava-retrying 实现业务逻辑重试功能,以下以调用第三方平台上传数据为例,直接贴代码如下
1.pom引入
<dependency>
<groupId>com.github.rholder</groupId>
<artifactId>guava-retrying</artifactId>
<version>1.0.6</version>
</dependency>
2. 封装顶层调用方法
/**
* 异步上报和保存交易系统实时交易或业务变动数据
* @param bankTransRequest 业务请求参数
* @param url 上报地址
* @param paramMap 上报参数
* @param keepParam 保留参数后续处理
*/
@Override
@Async
public void asyncTradeData(BankTransRequest bankTransRequest,String url,Map<String,Object> paramMap,Map<String, String> keepParam){
ClientExecutor executor = beanFactory.getBean(EnumClearingCenterTrans.getBySysTransCode(bankTransRequest.getTransCode(), "0").getBeanName(),ClientExecutor.class);
Map<String,Object> returnMap = new HashMap<String,Object>();
//根据上传标识确定是否请求上传
if(!StringUtils.equals("WAIT",keepParam.get("WAIT"))){
final String httpsUrl=new String(url);
final Map<String,Object> httpsParam=new HashedMap(paramMap);
returnMap=retryRequest(httpsUrl,httpsParam);
}
String data = (String) returnMap.get("data");
logger.info(EnumClearingCenterTrans.getBySysTransCode(bankTransRequest.getTransCode(), "0").getMessage()+"返回的data数据"+data);
//上报的其它数据已封装在keepParam
if(StringUtils.isBlank(data)){
logger.info("返回的data数据为空~~~~");
if(null != returnMap){
keepParam.put("errorCode", String.valueOf(returnMap.get("errorCode")));
keepParam.put("errorMsg", (String) returnMap.get("errorMsg"));
}
}else{
Gson gson = new Gson();
Map<String, Object> m = gson.fromJson(data, new TypeToken<Map<String, Object>>() {}.getType());
keepParam.put("errorCode", String.valueOf(m.get("errorCode")) );
keepParam.put("errorMsg", (String) m.get("errorMsg"));
}
executor.processReturnMessage(returnMap.toString(), bankTransRequest,keepParam);
}
3.重试业务逻辑
/**
* 异步上传(重试)
* @param httpsUrl
* @param httpsParam
* @return
* @throws Exception
*/
private Map<String,Object> retryRequest(final String httpsUrl,final Map<String,Object> httpsParam){
Map<String,Object> responseMap = new HashMap<String,Object>();
try {
Retryer<Map<String,Object>> retryer = RetryerBuilder.<Map<String,Object>>newBuilder()
.retryIfResult(new Predicate<Map<String, Object>>() {
@Override
public boolean apply(@Nullable Map<String, Object> soMap) {
//返回内容为空或不成功需要重新请求
String data = (String) soMap.get("data");
if( StringUtils.isBlank(data)){
return true;
}
Gson gson = new Gson();
Map<String, Object> formatData = gson.fromJson(data,new TypeToken<Map<String, Object>>() { }.getType());
if(!(StringUtils.equals(EnumClearingCenterMessage.MSG_SUCCESS.getCode(),(String)formatData.get(ClearingCenterMessageKey.KEY_ERROR_CODE))
|| StringUtils.equals(EnumClearingCenterMessage.MSG_SUCCESSES.getCode(),(String)formatData.get(ClearingCenterMessageKey.KEY_ERROR_CODE)))){
return true;
}
return false;
}
})
.retryIfExceptionOfType(IOException.class)
.retryIfRuntimeException()
.withWaitStrategy(WaitStrategies.fixedWait(RETRY_INTERVAL, TimeUnit.SECONDS)) // 重试间隔(配置参数)
.withStopStrategy(StopStrategies.stopAfterAttempt(RETRY_TIMES))//重试次数(配置参数)
)
.build();
responseMap=retryer.call(new Callable<Map<String,Object>>(){
public Map<String,Object> call() throws Exception {
return retryRequestCall(httpsUrl,httpsParam);
}
});
}
catch ( Exception e){
logger.error("重试请求异常:{}",e);
//重试器抛出异常获取不到请求返回信息,需手动补发一次
try {
responseMap=retryRequestCall(httpsUrl,httpsParam);
}
catch (Exception ex){
logger.error("重试补发请求异常:{}",ex);
}
}
finally {
return responseMap;
}
}
4.重试调用call方法
/**
* 重发call请求
* @param httpsUrl
* @param httpsParam
* @return
* @throws Exception
*/
protected Map<String, Object> retryRequestCall(String httpsUrl,Map<String,Object> httpsParam) throws Exception{
Map<String,Object> innerMap = new HashMap<String,Object>();
String message = HttpsClientUtil.request(httpsUrl, httpsParam, eventDispatcher.httpClientContext);
if(PsUtil.convertToNull(message)==null){
innerMap.put(return_code, "-1");
innerMap.put(return_message, "系统出现异常,请稍后再试");
}else{
innerMap= analysis(message);
}
return innerMap;
}
其它说明:
1. 封装顶层调用方法后方便加入@Async使服务调用异步执行,这样主业务可以继续处理其它业务。
2.如果淡出网络异常重试建议使用Httpclient的HttpRequestRetryHandler
参考资料:
http://blog.csdn.net/paul_wei2008/article/details/53871442
http://blog.csdn.net/aitangyong/article/details/53840719
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15020.html