Servlet3.0提供了非同步處理支援,SpringMVC對其進行了封裝,可以通過兩種方式進行非同步處理。 【1】Callable
官方文檔地址:
https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/web.html#mvc-ann-async-callable
其原理如下:
1、控制器返回Callable
2、Spring非同步處理,將Callable 提交到 TaskExecutor 使用一個隔離的線程進行執行
3、DispatcherServlet和所有的Filter退出web容器的線程,但是response 保持開啟狀態;
4、Callable返回結果,SpringMVC將請求重新派發給容器,恢複之前的處理;
5、根據Callable返回的結果。SpringMVC繼續進行視圖渲染流程等(從收請求-視圖渲染)。
程式碼範例如下:
@ResponseBody @RequestMapping("/async01") public Callable<String> async01(){ System.out.println("主線程開始..."+Thread.currentThread()+"==>"+System.currentTimeMillis()); Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { System.out.println("副線程開始..."+Thread.currentThread()+"==>"+System.currentTimeMillis()); Thread.sleep(2000); System.out.println("副線程開始..."+Thread.currentThread()+"==>"+System.currentTimeMillis()); return "Callable<String> async01()"; } }; System.out.println("主線程結束..."+Thread.currentThread()+"==>"+System.currentTimeMillis()); return callable; }
測試如下:
【2】DeferredResult
一旦啟用了非同步請求處理功能 ,控制器就可以將傳回值封裝在DeferredResult,控制器可以從不同的線程非同步產生傳回值。
優點就是可以實現兩個完全不相干的線程間的通訊。
首先建立一個儲存DeferredResult的執行個體
public class DeferredResultQueue { 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(); }}
兩個要求方法如下:
@ResponseBody @RequestMapping("/createOrder") public DeferredResult<Object> createOrder(){ DeferredResult<Object> deferredResult = new DeferredResult<>((long)3000, "create fail..."); DeferredResultQueue.save(deferredResult); return deferredResult; } @ResponseBody @RequestMapping("/create") public String create(){ //建立訂單 String order = UUID.randomUUID().toString(); DeferredResult<Object> deferredResult = DeferredResultQueue.get(); deferredResult.setResult(order); return "success===>"+order; }
首先http://localhost:8080/springmvc-annotation/createOrder請求擷取order,有結果返回,超出等待時間返回建立失敗。
http://localhost:8080/springmvc-annotation/create請求建立order,並給deferredResult賦值。