Spring MVC 3.2 預覽:介紹 Servlet 3 非同步支援

工程 | Rossen Stoyanchev | 2012 年 5 月 7 日 | ...

最後更新於 2012 年 11 月 5 日 (Spring MVC 3.2 RC1)

概述

Spring MVC 3.2 引入了基於 Servlet 3 的非同步請求處理。這是涵蓋此新功能的多篇博文中的第一篇,並提供了理解如何以及為何使用它的背景。

早期釋出的主要目的是尋求反饋。自 3.2 M1 版本釋出以來,我們在這裡和 JIRA 中收到了大量反饋。感謝所有嘗試並發表評論的人!有無數的更改,還有時間接受更多反饋!

一覽

從程式設計模型角度來看,新功能看似非常簡單。控制器方法現在可以返回一個 java.util.concurrent.Callable 以非同步完成處理。然後,Spring MVC 將在 TaskExecutor 的幫助下,在一個單獨的執行緒中呼叫 Callable。這是一段之前的程式碼片段。


// Before
@RequestMapping(method=RequestMethod.POST)
public String processUpload(final MultipartFile file) {
    // ...
    return "someView";
}

// After
@RequestMapping(method=RequestMethod.POST)
public Callable<String> processUpload(final MultipartFile file) {

  return new Callable<String>() {
    public Object call() throws Exception {
      // ...
      return "someView";
    }
  };
}

控制器方法還可以返回一個 DeferredResult(Spring MVC 3.2 中的新型別)以在 Spring MVC 未知的執行緒中完成處理。例如,響應 JMS 或 AMQP 訊息、Redis 通知等。這是另一段程式碼片段。


@RequestMapping("/quotes")
@ResponseBody
public DeferredResult<String> quotes() {
  DeferredResult<String> deferredResult = new DeferredResult<String>();
  // Add deferredResult to a Queue or a Map...
  return deferredResult;
}


// In some other thread...
deferredResult.setResult(data);
// Remove deferredResult from the Queue or Map

上述示例引出了許多問題,我們將在後續的博文中詳細介紹。現在,我將首先提供一些關於這些功能的背景資訊。

Web應用程式非同步化的動機

Web應用程式非同步化的最基本動機是處理耗時較長的請求。可能是緩慢的資料庫查詢、對外部REST API的呼叫,或其他一些I/O密集型操作。這些耗時較長的請求會迅速耗盡Servlet容器的執行緒池,影響可伸縮性。

在某些情況下,您可以在後臺作業完成處理的同時立即返回給客戶端。例如,傳送電子郵件、啟動資料庫作業以及其他“即發即棄”(fire-and-forget)場景,這些可以透過Spring的 @Async 支援,或者透過將事件釋出到 Spring Integration 通道來處理,然後返回一個客戶端可以使用該確認ID來查詢結果。

在其他需要結果的情況下,我們需要將處理與Servlet容器執行緒解耦,否則我們將耗盡其執行緒池。Servlet 3提供了這樣的支援,其中Servlet(或Spring MVC控制器)可以在Servlet容器執行緒退出後指示響應保持開啟狀態。

為了實現這一點,Servlet 3 Web應用程式可以呼叫 request.startAsync() 並使用返回的 AsyncContext 從其他獨立執行緒繼續寫入響應。同時,從客戶端的角度來看,請求仍然像任何其他HTTP請求-響應互動一樣。只是完成需要更長時間。以下是事件序列:

  1. 客戶端傳送請求
  2. Servlet容器分配一個執行緒並在其中呼叫一個Servlet
  3. Servlet呼叫 request.startAsync(),儲存 AsyncContext,然後返回
  4. 容器執行緒完全退出,但響應保持開啟狀態
  5. 其他執行緒使用已儲存的 AsyncContext 完成響應
  6. 客戶端接收響應

當然,Servlet非同步支援還有很多內容。您可以找到 各種 示例文件,但以上總結了您需要了解的基本、最低概念。 下一篇博文 將介紹非同步請求處理的第二個動機——瀏覽器接收即時資訊更新的需求。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有