天天看點

Servlet 異步處理一、AsyncContex簡介二、模拟伺服器推播

web容器會為每個請求配置設定一個線程,Servlet3.0新增了異步處理,解決多個線程不釋放占據記憶體的問題。可以先釋放容器配置設定給請求的線程與相關資源,減輕系統負擔,原先釋放了容器所配置設定線程的請求,其響應将被延後,可以在處理完成後再對用戶端進行響應。

    為了支援異步處理,在ServletRequest上提供了startAsync()方法。可以通過AsyncContext的getRequest()和getResponse()方法取得請求、響應對象,此次對用戶端的響應将暫緩至調用AsyncContext的complete()或dispatch()方法為止。

    首先要告知此容器支援Servlet異步處理,如:

    例1:異步處理的例子

AsyncServlet.java

    首先告訴容器,這個Servlet支援異步處理,對于每個請求,Servlet會取得其AsyncContext,并釋放容器所配置設定的線程,響應被延遲後。對于這些被延遲後響應的請求,建立一個實作Runnable接口的AsyncRequest對象,并将其排程一個固定數量的線程池,讓這些必須長時間處理的請求,線上程池中完成,不用每次配置設定線程。

    例2:AsyncRequest是個實作Runnable的類,其模拟了長時間處理。

AsyncRequest.java

    以暫停線程的方式來模拟長時間處理,并輸出簡單的文字,最後調用complete()對用戶端完成響應。

    HTTP是基于請求、響應模型,如果用戶端要獲得伺服器的最新狀态,就必須以定期方式發送請求,查詢伺服器端的最新狀态。

    Servlet 3.0提供的異步處理技術,可以解決每個請求占用線程的問題,再結合Ajax異步請求技術,就可以達到類似伺服器主動通知浏覽器的行為。這就是所謂的伺服器端推播。

    例3:模拟應用程式不定期産生最新資料,這個部分由實作ServletContextListener的類負責,會在程式啟動時進行。

WebInitListener.java

    有個List會存儲所有的異步請求的AsyncContext,并在不定時産生數字後,逐一對用戶端響應,并調用AsyncContext的conmplete()來完成請求。

    負責接收請求的Servlet,一收到請求,就将之加入到List中。

AsyncNumServlet.java

    由于List是儲存為ServletContext屬性,是以在Servlet中,必須從ServletContext中取出,每次請求到來時,調用HttpServletRequest的startAsync()進行異步處理,并取得AsyncContext加入維護AsyncContext的List中。

    可以使用一個簡單的HTML,使用Ajax技術,發送異步請求值伺服器端,這個請求會被延遲,直到伺服器端完成響應後,更新網頁上的資料,并再度發送異步請求:

async.html

    可以試着用多個浏覽器請求這個頁面,會看到每個浏覽器的資料是同步的。

當神已無能為力,那便是魔渡衆生