当一个请求到达API接口,如果该API接口的return返回值是DeferredResult,在没有超时或者DeferredResult对象设置setResult时,接口不会返回,但是Servlet容器线程会结束,DeferredResult另起线程来进行结果处理,并setResult,如此以来这个请求不会占用服务连接池太久,如果超时或设置setResult,接口会立即返回。
使用DeferredResult的流程:
- 浏览器发起异步请求
- 请求到达服务端被挂起
- 向浏览器进行响应,分为两种情况:
3.1 调用DeferredResult.setResult()
,请求被唤醒,返回结果
3.2 超时,返回一个你设定的结果 - 浏览得到响应,再次重复1,处理此次响应结果
@Controller public class AsycController { @RequestMapping("create") @ResponseBody public DeferredResult<Object> create(){ DeferredResult<Object> deferredResult=new DeferredResult<Object>((long)5000,"create fail"); DeferredQueue.save(deferredResult); return deferredResult; } @RequestMapping("get") @ResponseBody public String get(){ String orderid= UUID.randomUUID().toString(); DeferredResult<Object> deferredResult=DeferredQueue.get(); deferredResult.setResult(orderid); return "get orderid="+orderid; } }
public class DeferredQueue { private static Queue<DeferredResult<Object>> queue=new ConcurrentLinkedQueue<DeferredResult<Object>>(); public static void save(DeferredResult<Object> deferredResult){ queue.add(deferredResult); } public static DeferredResult<Object> get(){ return queue.poll(); } }
请求create 后 5秒内 请求 get 则异步结束 返回 结果