60、springmvc-异步请求-返回Callable
@Controller
public class AsyncController {
@RequestMapping("async01")
@ResponseBody
public Callable async01() {
System.out.println("主线程开始..." + Thread.currentThread() + "===》" + System.currentTimeMillis());
Callable callable = new Callable() {
public String call() throws Exception {
System.out.println("子线程开始..." + Thread.currentThread() + "===》" + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("子线程结束..." + Thread.currentThread() + "===》" + System.currentTimeMillis());
return "Callable 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 运行结果
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());
}