60、springmvc-異步請求-返回Callable
@Controller
public class AsyncController {
@RequestMapping("async01")
@ResponseBody
public Callable<String> async01() {
System.out.println("主線程開始..." + Thread.currentThread() + "===》" + System.currentTimeMillis());
Callable<String> callable = new Callable<String>() {
public String call() throws Exception {
System.out.println("子線程開始..." + Thread.currentThread() + "===》" + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("子線程結束..." + Thread.currentThread() + "===》" + System.currentTimeMillis());
return "Callable<String> async01()";
}
};
System.out.println("主線程結束..." + Thread.currentThread() + "===》" + System.currentTimeMillis());
return callable;
}
}
60.1 Spring MVC異步執行
- 控制器返回Callable
- Spring異步處理,將Callable 提交到 TaskExecutor 使用一個隔離的線程進行執行
- DispatcherServlet和全部的Filter退出web容器的線程,可是response 保持打開狀態;
- Callable返回結果,SpringMVC將請求從新派發給容器,恢復以前的處理;
- 根據Callable返回的結果。SpringMVC繼續進行視圖渲染流程等(從收請求-視圖渲染)。
60.2 運行結果
![](http://static.javashuo.com/static/loading.gif)
60.3 異步攔截器
- 原生API的
AsyncListener
- SpringMVC:實現
AsyncHandlerInterceptor
;
60.4 注意警告。
- 查看執行類源碼
org.springframework.web.context.request.async.WebAsyncManager
有這麼一段獲取
- 若是沒有指定
AsyncTaskExecutor
就會 warning 警告 logExecutorWarning();
AsyncTaskExecutor executor = webAsyncTask.getExecutor();
if (executor != null) {
this.taskExecutor = executor;
}
else {
logExecutorWarning();
}
- 解決:咱們能夠本身配置一個線程池來執行,以下
- 經過在
AppConfig implements WebMvcConfigurer
中 configurer.setTaskExecutor(threadPoolTaskExecutor());
來執行
/**
* 自定義 異步任務執行線程池,解決warnning警告
* @return
*/
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.initialize();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setThreadNamePrefix("JHW");
return executor;
}
@Bean
public TimeoutCallableProcessingInterceptor timeoutCallableProcessingInterceptor() {
return new TimeoutCallableProcessingInterceptor();
}
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(threadPoolTaskExecutor());
configurer.setDefaultTimeout(60 * 1000L);
configurer.registerCallableInterceptors(timeoutCallableProcessingInterceptor());
}
![](http://static.javashuo.com/static/loading.gif)