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 容器執行緒池並影響可伸縮性。

在某些情況下,您可以立即返回給客戶端,而後臺作業完成處理。例如,傳送電子郵件、啟動資料庫作業等代表了即發即棄場景,可以使用 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 社群中所有即將舉行的活動。

檢視全部