2011-05-10 132 views
1

我無法爲用戶建立AsyncContext並使用它們向他們推送通知。在頁面加載我有一些jQuery代碼來發送請求:Servlet 3.0:無法發送異步響應?

$.post("TestServlet",{ 
    action: "registerAsynchronousContext" 
     },function(data, textStatus, jqXHR){ 
      alert("Server received async request"); //Placed here for debugging 
    }, "json"); 

而在「的TestServlet」我有這樣的代碼在doPost方法:

HttpSession userSession = request.getSession(); 
String userIDString = userSession.getAttribute("id").toString(); 

String paramAction = request.getParameter("action"); 

if(paramAction.equals("registerAsynchronousContext")) 
{    
    AsyncContext userAsyncContext = request.startAsync(); 

    HashMap<String, AsyncContext> userAsynchronousContextHashMap = (HashMap<String, AsyncContext>)getServletContext().getAttribute("userAsynchronousContextHashMap"); 
    userAsynchronousContextHashMap.put(userIDString, userAsyncContext); 
    getServletContext().setAttribute("userAsynchronousContextHashMap", userAsynchronousContextHashMap); 

    System.out.println("Put asynchronous request in global map"); 
} 

    //userAsynchronousContextHashMap is created by a ContextListener on the start of the web-app 

然而,根據Opera蜻蜓(調試像Firebug這樣的工具),看起來服務器在發送請求後發送大約30000ms的HTTP 500響應。

任何使用userAsyncContext.getResponse()。getWriter()。print(SOME_JSON)創建並在HTTP 500響應未被瀏覽器接收之前發送的響應,我不知道爲什麼。僅當處理AsyncContext的「if」語句中的所有代碼都不存在時,瀏覽器纔會收到使用常規響應對象發送響應(response.print(SOME_JSON))。

有人可以幫我嗎?我有一種感覺,這是因爲我誤解了異步API的工作原理。我認爲我可以將這些AsyncContext存儲在全局映射中,然後檢索它們並使用它們的響應對象將事物推送到客戶端。但是,它似乎並不像AsyncContexts可以寫回客戶端。

任何幫助將被處理。

回答

5

我解決了這個問題。它好像有幾個問題錯了我的做法:

  1. GlassFish中,AsyncContext對象均具有30000毫秒(0.5分鐘),默認的超時時間。一旦這段時間到期,整個響應都會返回給客戶端,這意味着您將無法再使用它。

    如果您正在實施長輪詢,這可能不是什麼大問題(因爲您最終會在響應之後發送另一個請求),但是如果您希望實現流式傳輸(發送數據返回到客戶端沒有提交響應),你會想要增加超時時間,或者一起擺脫它。 這可以通過AsyncContext的.setTimeout()方法來完成。請注意,儘管spec指出:「超時值爲零或更低表示沒有超時。」,Glassfish(目前)似乎將0解釋爲「立即響應要求」,任何負數解釋爲「無超時」。

  2. 如果你實現流,你必須使用的PrintWriter的.flush()方法,你使用它的.print().println().write()方法將數據寫入完成後,將數據推送到客戶端。在客戶端,如果你已經對數據進行了流式處理,它將觸發3的readyState(「交互式」,這意味着瀏覽器正在接收響應)。如果你使用jQuery,沒有簡單的方法來處理3的readyStates,所以你將不得不恢復到正常的Javascript,以便發送請求並處理響應,如果你正在實現流。

2

我注意到,在Glassfish的,如果你使用AsyncContext和使用.setTimeOut()爲負數的連接反正壞了,要解決這個問題,我不得不去我的GlassFish管理web界面:asadmin的設置 configs.config.server-config.network-config.protocols.protocol。HTTP偵聽器1.http。並將超時設置爲-1。所有這些以避免玻璃魚在30秒後完成連接。