Spring官方的Spring框架文档中,针对异步请求:提供了两个类来实现: DeferredResult 和 Callable
Spring中的DeferredResult 设计思想 提供了使用可调用异步请求处理的替代方案,可以给一个线程A的结果设置为DeferredResult。 之后,在另一个线程B对A线程的该结果进行赋值。 主要属性 结果超时时间 timeout 超时默认结果 timeoutResult 超时执行函数 timeoutCallback 完成执行函数 completionCallback
设置结果方法 DeferredResult.setResult()方法
项目使用DeferredResult的具体场景 场景描述: 收费员端根据信息,发起收费(在一个平板上显示二维码),患者通过手机进行支付。 由于,接口被请求后(收费员端携带收费信息),患者需要时间进行支付,所以接口请求后,需要等待一段时间,才有最终结果。 此时,对于接口调用方来说:是同步的,因为一个调用,一个结果。 但是对于被调用方,是异步的,因为,该线程收到支付请求后,并不知道是否支付成功。需要另外的线程进行通知。 一句话描述:结果在一个线程中不能马上得到,需要时间进行处理,之后另一个线程进行统通知。
DeferredResult和Servlet的关系
DeferredResult原理 Spring框架帮我们做了很多事情。 DeferredResult这个实现,和web请求是强相关的,只有web请求时,才会用到该类。
DeferredResult and Callable return values in controller methods and provide basic support for a single asynchronous return value.-官方文档
DeferredResult的处理流程如下(来自官方文档): 1、控制器返回DeferredResult,(我们使用者)并将它保存在可以访问的内存队列或者列表中; 2、Spring调用request.startAsync();(我的理解,调用该方法后,该Servlet 线程结束,故Tomcat的Servlet线程池中的线程得到释放,可以进行其他的请求处理) 3、DispatcherServlet和过滤器退出处理线程,但响应保持打开 4、DeferredResult从某个线程被设置,Spring MVC将请求分派回Servlet容器; 5、DispatcherServlet被调用,处理和返回最终值
备注: Spring的DispatcherServlet这个模块设计到Servlet结果的赋值,如果要想完全了解DeferredResult背后Spring的工作机制,那么需要研究下。 如下:
@ApiOperation(value = "接口一") @GetMapping("/order") public DeferredResult<OrderInfo> createOrder(String outTradeNo) { DeferredResult<OrderInfo> result = new DeferredResult<>(); OrderDeferredResultSupporter.registDeferredResult(outTradeNo, result); return result; }