60、springmvc-異步請求-返回Callable

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異步執行

  1. 控制器返回Callable
  2. Spring異步處理,將Callable 提交到 TaskExecutor 使用一個隔離的線程進行執行
  3. DispatcherServlet和全部的Filter退出web容器的線程,可是response 保持打開狀態;
  4. Callable返回結果,SpringMVC將請求從新派發給容器,恢復以前的處理;
  5. 根據Callable返回的結果。SpringMVC繼續進行視圖渲染流程等(從收請求-視圖渲染)。

60.2 運行結果

60.3 異步攔截器

  1. 原生API的AsyncListener
  2. 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 WebMvcConfigurerconfigurer.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());
}

相關文章
相關標籤/搜索