2010-03-02 74 views
6

我有一種似乎適合異步Servlet 3.0/Comet情況的情況,但我需要做的是在接受傳入參數後返回200響應代碼(或其他)。完成HttpServletResponse,但繼續處理

有沒有辦法讓HttpServlet完成http請求/響應握手並繼續處理?

喜歡的東西...

doPost(req, response) { 
    // verify input params... 
    response.setStatus(SC_OK); 
    response.close(); 
    // execute long query 
}  

編輯:縱觀javax.servlet包 - 適當的措辭我的問題是

如何犯下的反應?

在Servlet.isCommitted()

+0

「承諾」是指響應流中的某些部分已經被髮送到客戶端。它不能被收回或修改。理論上,只要您設置標題或寫入響應,它就會發生,但通常是容器緩衝區,所以稍後會發生。 我認爲這與你無關。不要關閉響應流。只需設置狀態,按照其他答案啓動線程,讓doPost()完成。 – 2010-03-05 12:15:35

+0

我試着使用response.sendError(SC_OK),但它仍然沒有刷新對請求者的響應。看起來,關閉servlet請求的唯一方法是從doPost()返回。 – Stevko 2010-03-05 17:49:51

回答

6

這裏是我是如何處理這種情況:

  1. 當應用程序啓動時,創建一個ExecutorServiceExecutors.newFixedThreadPool(numThreads)(還有其他類型的執行者,但我建議先從這一個)
  2. doPost(),創建Runnable一個實例將執行所需的處理 - 你的任務 - 它提交給ExecutorService像這樣:executor.execute(task)
  3. 最後,你應該返回的HTTP狀態202 Accepted,而且,如果可能的話,一個Location標題指示客戶端將能夠檢查處理狀態的位置。

強烈建議您閱讀Java Concurrency in Practice,這是一個夢幻般的,非常實用的書。

+0

雖然我同意所有的答案,但這個答案涉及的複雜度最小。感謝pajton,beny23和avi供您參考。 – Stevko 2010-03-05 17:48:01

+0

我該如何做到這一點,如果我想使用executor.submit()而不是.execute?我想使用.submit,以便我可以掌握「未來」,並知道所有任務何時完成(基於哪些我必須執行某些處理?)。 – Tintin 2017-01-27 16:10:42

3

您可以繼續在一個單獨的線程處理。

doPost()方法返回後,提交響應。

+0

我正在運行URL提取服務5秒超時,請求源自Google應用引擎的完美請求。 App Engine請求程序不需要阻止等待可能需要很長時間才能完成處理的確定響應。 – Stevko 2010-03-02 23:35:48

+0

好吧,所有你需要的只是後臺線程:)。 – pajton 2010-03-02 23:37:35

3

關於您的servlet接受後臺處理請求的可能性,是讓servlet將處理交給單獨的線程,然後在後臺執行。

使用Spring,可以使用a TaskExecutor調用單獨的線程。使用Spring比標準JDK 5 java.util.concurrent.Executor的優勢在於,如果您使用的是需要使用託管線程(IBM websphere或Oracle weblogic)的應用程序服務器,則可以使用WorkManagerTaskExecutor掛接到CommonJ工作管理器。

另一種選擇是將長查詢邏輯移動到消息驅動Bean或消息驅動POJO(Spring JMS可以在這裏幫助),並讓servlet簡單地在JMS隊列上發佈消息。這樣做的好處是,如果由於長時間運行的查詢而導致Web容器上的負載變得太大,則可以輕鬆地將MDB移動到不同的(專用)系統上。

0

這個例子可以幫助

void doPost(){ 
    // do something 
    final ExecutorService executor = Executors.newSingleThreadExecutor(); 
     executor.execute(new Runnable() { 
      @Override 
      public void run() { 
       // processing after response 
      } 
     });} 
+1

你能介紹一下嗎? – 2015-04-06 18:44:05

+0

最好不要在每次servlet獲取請求時實例化一個ExecutorService,否則您將開始創建大量永不死亡的線程,至少每個newSingleThreadExecutor()文檔都是如此。 – 2018-03-06 19:54:08