分享一次 在工作上 没有MQ的 通过单起线程做状态处理
最近需要一个合同签署的第三方接口,由于该接口的处理响应较慢,每次会请求超时,所以需要一个补偿接口,也就是状态同步接口,如果有MQ工具的最好用MQ来实现,不过思路是差不多的。
我和第三方在商定后,第三方给出一个状态回响接口,来进行状态同步,而我则把状态落库,对于我方H5的调用进行秒响应的形式。
下面展示一些 内部代码 没前后关联的地方我都用注解说明了下 主要是一个思想
。
//state 1签订成功 2签署中 3签订失败
//第三方接口 接口返回当前状态
PCContractEntity pcContractEntity = new PCContractEntity();
pcContractEntity.setPReserveno(signEcontractDTO.getPReserveno());
smEntity.setStatus("2");
int i = pcContractDao.updateByPrimaryKeySelective(smEntity);//落库状态
if (i != 0) {//数据update成功
new Thread(new Runnable() {//方法里起个个线程处理状态
@Override
public void run() {
//先判断库内 状态是否已经 1签订成功
PCContractEntity pcContractEntity = new PCContractEntity();
pcContractEntity.setPReserveno(signEcontractDTO.getPReserveno());
PCContractEntity smEntity = pcContractDao.selectOne(pcContractEntity);
logger.info("合同当前状态:{}", smEntity);
if (smEntity != null && StringUtil.isNotEmpty(smEntity.getStatus())) {
boolean flag = "2".equals(smEntity.getStatus()) ? true : false;//循环开关
int er = 0;//错误计数
int suc = 0;//成功计数
while (flag) {
if (suc > 40 || er > 5) { //10分钟的调用
//10分钟的调用之后 未成功 默认失败处理
PCContractEntity newContractEntity = new PCContractEntity();
newContractEntity.setId(smEntity.getId());
newContractEntity.setStatus("3");
pcContractDao.updateByPrimaryKeySelective(newContractEntity);
flag = false;//停止循环
}
suc++;
HashMap<String, String> param = new HashMap<>();
param.put("p_reserveno", signEcontractDTO.getPReserveno());
logger.info("****入参**** paramState={}", param);
try {
//第三方调用采用form-data形式调用
String postJson=HttpTool.nFormPost(DJInterfaceInfo.CONTRACT.getUrl(urlAddress.getUrl()), param);
JSONObject stateJson = JSONObject.parseObject(postJson);//接取 响应用JSONObject来灵活处理
log.info("****第{}次合同状态 结果****parseObject={}", suc, stateJson);
if (stateJson.getInteger("code") == ResultEntity.SUCCESS.getCode()) {
//code 200 签订请求成功
// state 1签订成功 2签署中 3签订失败
if ("1".equals(stateJson.getString("state"))) {
PCContractEntity newContractEntity = new PCContractEntity();
newContractEntity.setId(smEntity.getId());
newContractEntity.setStatus("1");
pcContractDao.updateByPrimaryKeySelective(newContractEntity);
flag = false;//停止循环
} else if (StringUtil.isEmpty(stateJson.getString("state"))) {//未查到数据
log.info("数据未查到 ");
flag = false;//停止循环
} else if ("3".equals(stateJson.getString("state"))) { //签署失败
PCContractEntity newContractEntity = new PCContractEntity();
newContractEntity.setId(smEntity.getId());
newContractEntity.setStatus("3");
pcContractDao.updateByPrimaryKeySelective(newContractEntity);
flag = false;//停止循环
}
} else {//请求状态不是 200
er++;
}
} catch (Exception e) {
er++;
logger.error("接口异常:{}", e);
} finally {
try {
log.info("~~~~~~~~~~阻塞 15s~~~~~");
Thread.sleep(15000);
} catch (InterruptedException e) {
er++;
logger.error("线程阻塞异常", e);
}
}
}
}
log.info("***********************合同状态同步线程线程 结束********************");
}
}).start();
}
return Result.success(map).setMessage("合同签署中");
}
这个逻辑主要是对业务的灵活处理,和灵活使用线程来异步处理状态。
我会再用一个状态查询方法,只做一个数据库的查询状态操作。当然这个状态落库也可以落在Redis缓存中,根据业务来选择。