背景:
需求:
可以实时获取啄木鸟伍迪的访问数据、排名、积分等数据,可以实时现在在网站后台页面的大屏上;
解决方案:
可以使用异步请求,springmvc默认的请求都是同步的,也就是请求过去,必须得有处理完成,否则就回阻塞;异步请求是当发起一个请求,可以暂时没有响应,请求回被挂起不阻塞;请求过去,就返回一个DeferredResult,该DeferredResult可以在其他线程中返回需要的结果,也就是执行DeferredResult.setResult(),此时,异步请求回被唤醒
;
DeferredResult的流程:
- 浏览器发起异步请求
- 请求到达服务端被挂起
- 向浏览器进行响应,分为两种情况:
3.1 调用DeferredResult.setResult()
,请求被唤醒,返回结果
3.2 超时,返回一个你设定的结果 - 浏览得到响应,再次重复1,处理此次响应结果
如果定时任务去获取啄木鸟伍迪的访问数据、排名、积分等数据,当前定时任务处理完了,就告诉页面有数据了,马上ajax查询最新数据;页面重新执行ajax 的查询数据的函数即可;
官网给的例子:
@GetMapping("/quotes") @ResponseBody public DeferredResult<String> quotes() { DeferredResult<String> deferredResult = new DeferredResult<>(); // 返回一个DeferredResult return deferredResult; } // 其他线程处理结果; deferredResult.setResult(result);
DeferredResult的使用步骤:
1.spring开启异步请求:
需要在web.xml 的filter 和DispatcherServlet 中配置 :<async-supported>true</async-supported>;
配置方式可以参考https://www.cnblogs.com/lixiuming521125/p/17622238.html
2.添加异步请求
/** * 异步请求 * @return */ @RequestMapping("/quotes") @ResponseBody public DeferredResult<String> quotes() { //设置了1分钟超时 DeferredResult<String> deferredResult = new DeferredResult<>(60000L); //放入缓存中,可全局调用 CacheUtils.put(CacheUtils.DEFERRED_CACHE_NAME, ShiroUtils.getUsername(),deferredResult); return deferredResult; }
3.页面的异步请求:
function updateDashboardData(){ //循环发送异步请求; //设置了定时器,防止页面崩溃; if(!!timeUpdate.quotesTimeout){ clearTimeoutFun(timeUpdate.quotesTimeout); } $.ajax({ type : 'post', url : basePath + '/dashboard/quotes',//异步请求 contentType : "application/json;charset=utf-8", success : function(data) { if (!!data && data=="update") { updateData();//更新数据; } timeUpdate.quotesTimeout = setTimeout(updateDashboardData, 5000); }, error:function(){ timeUpdate.quotesTimeout = setTimeout(updateDashboardData, 5000); } }); }
4.定时任务调用DeferredResult.setResult(),唤起异步请求;(代码片段)
/** * 添加博客园每日数据 */ private void processMain() { ........... ................. logger.info("[TASK][CnblogDataDayTask].OTHER.DATA.PROCESS.END"); // 批量添加 logger.info("[TASK][CnblogDataDayTask].DELETE.DATA.DAY.EXIST"); addDayList = resultList.stream().filter(s -> s.getAddDay() != null).map(CnblogDataDay::getAddDay) .collect(Collectors.toList()); cnblogDataDayService.delete(addDayList); logger.info("[TASK][CnblogDataDayTask].INSERT.DATA.DAY"); if(CollectionUtils.isNotEmpty(resultList)){ cnblogDataDayService.insert(resultList); // 更新当前处理过的数据的 修改时间 logger.info("[TASK][CnblogDataDayTask].UPDATE.PROCESS.DATA"); cnblogDataDayService.updateModifyDate(endDate,DateUtils.toDate(syncTime, DateUtils.DATETIME_FORMAT)); updateBigScreem(); } } ..................... .......................... .................................. }
private void updateBigScreem() { List<Object> cacheKeys = CacheUtils.getKeys(CacheUtils.DEFERRED_CACHE_NAME); List<String> keys = getContainKey(cacheKeys, ShiroUtils.getUsername()); for (String key : keys) { Object obj = CacheUtils.get(CacheUtils.DEFERRED_CACHE_NAME, key); if (obj instanceof DeferredResult) { DeferredResult<String> result = (DeferredResult<String>)obj; result.setResult("update"); } } }
效果:
当请发起请求以后,执行了异步请求,且等待响应,如果此时执行了定时任务,如果此时执行了定时任务(在1分钟之内),那么该异步请求就处理完成了。
标签:异步,请求,quotes,springmvc,使用,deferredResult,CacheUtils,DeferredResult From: https://www.cnblogs.com/lixiuming521125/p/15722263.html