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());
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM