天天看點

[Java EE 7] Servlet 異步支援

伺服器資源非常寶貴,是以需要節省開銷。比如 servlet 需要等待資料庫查詢資料、等待生成報表、等待讀取檔案系統資料,等等。這些“長時間處理”将會完全地占用容器線程,于是,這些被占用的線程将無法再接收其它的請求,這對于珍貴的伺服器資源來說,并沒有做到最佳優化。

這些需要“長時間處理”的地方我們可以使用異步處理來進行優化,servlet 接收到請求後,開啟新的線程來進行長時間處理,并将容器線程返還給容器,這樣容器線程就可以繼續接收其它請求,等長時間運作的線程執行完成後,再使用和請求相同的容器線程響應到用戶端。

異步行為需要顯示地在 servlet 中聲明,可以在 @WebServlet 中添加 asyncSupported 屬性:

@WebServlet(urlPatterns="/async", asyncSupported=true)
public class MyAsyncServlet extends HttpServlet {
  //. . .
}
           

也可以在 web.xml 中設定 <async-supported> 元素的值為 true,也可以使用代碼的方式 ServletRegistration.setAsyncSupported(true)。

開始異步處理之前,需要調用 request 的 startAsync 方法來将容器線程分離。這個方法将會傳回 AsyncContext 對象,這個對象是異步處理上下文,你可以顯示地調用 AsyncContext.complete 來結束異步處理。

下面看看異步處理的例子:

class MyAsyncService implements Runnable {
  AsyncContext ac;

  public MyAsyncService(AsyncContext ac) {
    this.ac = ac;
  }

  @Override
  public void run() {
    //. . .
    ac.complete();
  }
}
           

這個服務可以在 doGet 中進行異步處理:

在上面的代碼中,request 開啟了異步模式。AsyncListener 用于監聽請求是否完成、逾時或出錯。MyAsyncService 作為長時間運作操作開啟了一個新的線程,并且調用了 AsyncContext.complete 方法送出請求已完成的信号。

請求可以從異步的 servlet 發送到同步的 servlet,但是反過來卻是非法的。

異步處理在 servlet filter 中也适用。

文章來源:[url]http://www.aptusource.org/2014/04/java-ee-7-asynchronous-support/[/url]