以下內容均來自於官方文檔
1.為什么要異步支持?
應用服務器中的Web容器通常使用每個客戶機請求的服務器線程。在重負載條件下,容器需要大量的線程來滿足所有客戶機請求。可伸縮性限制包括耗盡內存或耗盡容器線程池。要創建可伸縮的web應用程序,您必須確保沒有與請求關聯的線程處於閑置狀態,因此容器可以使用它們來處理新請求。
簡單點說,就是為了節約服務器端的資源
2.異步支持的應用場景
①.在構建響應之前,線程需要等待資源變為可用或處理數據。比如,一個應用程序需要查詢數據庫或者在生成響應之前從遠程web服務訪問數據。
②.在生成響應之前,線程需要等待一個事件。比如,一個應用程序可能必須等待一個JMS信息,在生成響應之前,等待來自另一個客戶機的新信息或在隊列中可用的新數據。
這些場景表示限制web應用程序可伸縮性的操作。異步處理指將這些阻塞操作分配給一個新線程,並將與請求關聯的線程重新調整到容器
3.sevlet中的異步處理
Java EE為servlet和過濾器提供異步處理支持。如果servlet或過濾器在處理請求時達到了潛在的阻塞操作,它可以將操作分配給異步執行上下文,並將與請求關聯的線程立即返回到容器中,而不會生成響應。阻塞操作在不同線程中完成異步執行上下文,可以生成響應或將請求發送給另一個servlet。
要在servlet上啟用異步處理,可以在@WebServlet注解上將參數asyncsupport設置為true:

javax.servlet.AsyncContext類提供了在服務方法中執行異步處理所需的功能。要獲得一個AsyncContext實例,請在服務方法的請求對象上調用startAsync()方法;例如:

此調用將請求放入異步模式,並確保在退出服務方法后不會提交響應。在阻塞操作完成或將請求發送到另一個servlet之后,你必須在異步上下文中生成響應。
容器提供了一個不同的線程,其中阻塞操作可以被處理。
AsyncContext類提供的方法:
void start(Runnable run):為阻塞操作提供代碼,作為實現Runnable接口的類。當調用start方法或使用其他機制將 AsyncContext實例傳遞給類時,您可以將該類作為一個內部類提供。
ServletRequest getRequest():返回用於初始化此異步上下文的請求。在上面的示例中,請求與服務方法相同。
你可以使用這個方法在異步上下文獲取從請求參數。
ServletResponse getResponse():返回用於初始化此異步上下文的響應。在上面的示例中,響應與服務方法相同。
你可以在異步上下文中使用此方法來將阻塞操作的結果寫入響應。
void complete():完成異步操作並關閉與此異步上下文關聯的響應。在異步上下文中寫入響應對象之后,調用此方法。
void dispatch(String path):將請求和響應對象分派到給定的路徑。在阻塞操作完成之后,使用此方法讓另一個servlet寫入響應。
4.實例


MyRemoteResource是一個模擬的資源類。
解釋:
在上面的列子中,startasync()使請求被異步處理;在服務方法結束時,不會將響應發送到客戶端。acontext.start(new Runnable(){})從容器中獲取一個新線程。
內部類的run()方法中的代碼在新線程中執行。內部類可以訪問異步上下文,從請求中讀取參數並寫入響應。調用異步上下文的complete()方法提交響應並將其發送給客戶機。
AsyncServlet的服務方法立即返回,請求在異步上下文中處理。
