九.CompletableFuture使用
需求
需要一个同步返回结果,可是同步返回结果依赖另一个异步操作.希望能把异步操作封装成同步动作.这个封装工具就能用大名鼎鼎的
CompletableFuture
案例
/**
获得的同步返回结果有两种信息,
一种是需要等待第三方callback有用信息的(async),
另一种直接返回有用信息(sync).
future 里面通过 complete 方法放入一个 value,
再通过 get 方法将其取出
**/
//创建一个Future
messageHandler.buildFuture(accountValidationRequest.orderId)
return try {
when (response) {
//同步,直接映射成需要的结果并返回
sync -> Util.mapToBankAccountProbingResponse(request, accountValidationResponse)
//异步,映射一个未来的结果
async ->Util.mapToBankAccountProbingResponse(request, messageHandler.waitCallBack(response.orderId!!)
}
} catch (e: TimeoutException) {
logger.info("has not receive callback from chinapnr in {} sec,call resultCheck interface", WAITINGTTL)
val resultCheckRequest = ResultCheckRequest(accountValidationRequest.orderId, accountValidationResponse.seqId!!)
Util.mapToBankAccountProbingResponse(request, accountValidationProxy.resultCheck(resultCheckRequest))
} finally {
//最后,把Futuare移除
messageHandler.removeFuture(accountValidationRequest.orderId)
}
MessageHandler
@Component
class MessageHandler {
@Value("\${awx.chinapnr.wait_time}")
private var timeOut: Long = 5
private var logger = LoggerFactory.getLogger(MessageHandler::class.java)
//定义一个ConpletableFutlre 的 ConcurrentHashMap,在创建Future和delete Future 时能保证不会受到重复请求的干扰
定义futuare中value的类型为AccountValidationResponse
var mapper = ConcurrentHashMap<String, CompletableFuture<AccountValidationResponse>>()
//创建future方法
fun buildFuture(orderId: String) {
mapper[orderId] = CompletableFuture()
}
//获取future方法,定义了timeout,超时直接报timeout异常,返回
fun waitCallBack(orderId: String): AccountValidationResponse? {
var future = mapper[orderId]
//取出future的value
return future!!.get(timeOut, TimeUnit.SECONDS)
}
//futureComplete条件
fun sendCallBackMessage(orderId: String, accountValidationResponse: AccountValidationResponse) {
var future = mapper[orderId]
//通过complete设置future的value
future?.complete(accountValidationResponse)
?: logger.error("receive an unexpected callback from chinapnr, orderId: {}", orderId)
}
//删除future
fun removeFuture(orderId: String) = mapper.remove(orderId)
}
FutureComplete条件: 在timeout前收到第三方的callback
@RestController
@RequestMapping("/v1")
class CallBackHandler {
private var logger = LoggerFactory.getLogger(CallBackHandler::class.java)
@Autowired
private lateinit var messageHandler: MessageHandler
@RequestMapping(produces = ["application/x-www-form-urlencoded"], value = "/infovalidation", method = [RequestMethod.POST, RequestMethod.GET])
fun callBack(request: CallBackRequest): String {
logger.info("callback request from chinapnr: " + Codecs.objToJsonString(request))
var seqId = request.seq_id
var accountValidationResponse = mapToAccountValidationResponse(request)
messageHandler.sendCallBackMessage(request.order_id, accountValidationResponse)
return "RECV_ORD_ID_$seqId"
}
private fun mapToAccountValidationResponse(request: CallBackRequest): AccountValidationResponse {
return AccountValidationResponse(
request.return_code!!,
request.return_message,
request.resp_code,
request.resp_info,
request.seq_id,
request.order_id,
""
)
}
}
扩展阅读
https://www.jianshu.com/p/6f3ee90ab7d3