使用场景
@RequestMapping(value = "/cheStopWithoutAuth")
@ResponseBody
public WebAsyncTask<AjaxResponse> cheStop(String port,
AjaxResponse ar) throws Exception {
log.info("主线程开始");
Callable<AjaxResponse> result = (() -> {
log.info("副线程开始");
cheService.cheStop(port);
ar.setSuccessMessage(ResultEnums.SUCCESS.getMessage(), null);
log.info("副线程结束");
return ar;
}); //直接Callable也可以,但是不能设置超时时间和超时回调以及成功回调
WebAsyncTask<AjaxResponse> webAsyncTask = new WebAsyncTask<>(300000, result);
webAsyncTask.onTimeout(timeOutCallBack());
log.info("主线程结束");
return webAsyncTask;
}
/**
* 超时回调
*/
private Callable<AjaxResponse> timeOutCallBack(){
Callable<AjaxResponse> callback = (()-> {
log.info("请求超时");
AjaxResponse ajaxResponse = new AjaxResponse();
ajaxResponse.setErrorMessage("请求超时",null);
return ajaxResponse;
});
return callback;
}
注意web.xml应用需在所有的servlet和filter配置加上<async-supported>true</async-supported>
filter放置位置
servlet放置位置
使用场景
@Data
@Slf4j
@Component
public class MockQueue {
private String placeOrder; //下单消息
private String completeOrder; //订单完成的消息
public void setPlaceOrder(String placeOrder) throws InterruptedException {
new Thread(()->{
log.info("接单下单请求");
try {
Thread.sleep(1000); //模拟应用2处理下单的过程
} catch (InterruptedException e) {
e.printStackTrace();
}
this.completeOrder = placeOrder; //给completeOrder设值代表下单请求处理完毕
log.info("下单请求处理完毕:{}",placeOrder);
}).start();
}
public void setCompleteOrder(String completeOrder) {
this.completeOrder = completeOrder;
}
}
@Component
@Data
public class DeferredResultHolder {
//key:订单号 value:订单的处理结果
private Map<String,DeferredResult<String>> map = new HashMap<>();
}
/**
* ContextRefreshedEvent 整个容器初始化完毕的一个事件
*/
@Component
@Slf4j
public class QueueListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private MockQueue mockQueue;
@Autowired
private DeferredResultHolder deferredResultHolder;
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
new Thread(() ->{
while (true){
if(StringUtils.isNotBlank(mockQueue.getCompleteOrder())){ //当订单完成的字段有值,说明有完成的订单
String orderNumber = mockQueue.getCompleteOrder();
log.info("返回订单处理结果:"+orderNumber);
deferredResultHolder.getMap().get(orderNumber).setResult("place order success");
mockQueue.setCompleteOrder(null);
}else{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
@RequestMapping("/order2")
public DeferredResult<String> order2() throws InterruptedException {
log.info("主线程开始");
String orderNumber = RandomStringUtils.randomNumeric(8); //生成8位订单号
mockQueue.setPlaceOrder(orderNumber);
DeferredResult<String> result = new DeferredResult<>();
deferredResultHolder.getMap().put(orderNumber,result);
log.info("主线程返回");
return result;
}
注意SprinbBoot中对异步请求注册过滤器应继承WebMvcConfigurerAdapter并重写configureAsyncSupport方法
image.png