SpringMVC非同步處理的 5 種方式

2022-06-01 14:36:09 字數 2738 閱讀 6102

前段時間研究了下 diamond 的原理,其中有個重要的知識點是長連線的實現,用到了 servlet 的非同步處理。非同步處理最大的好處是可以提高併發量,不阻塞當前執行緒。其實 spring mvc 也支援了非同步處理,本文記錄下相關的技術點。

如果要啟用非同步返回,需要開啟 @enableasync。如下的**中,使用 deferredresult 進行非同步處理。

請求進來後,首先建立 deferredresult 物件,設定超時時間為 60 秒。然後指定 deferredresult 在非同步完成和等待超時時的**。同步的處理只需要建立非同步任何,然後返回 deferredresult 即可。這樣 spring mvc 處理完此次請求後,不會立即返回 response 給客戶端,會一直等待 deferredresult 處理完成。如果 deferredresult 沒有在 60 秒內處理完成,就會觸發超時,然後返回 response 給客戶端。

public deferredresultasync()

對於非同步任務來說,需要持有 deferredresult 物件。在非同步處理結束時,需要手動呼叫 deferredresult.setresult完成輸出。呼叫 setresult 時,資料輸出寫到客戶端,然後觸發非同步完成事件執行**。

task.getdeferredresult().setresult(configjsonutils.tojsonstring(map));

deferredresult 這個類代表延遲結果。deferredresult 可以用在非同步任務中,其他執行緒能夠獲取 deferredresult 並設定 deferredresult 的返回資料。通常可以使用執行緒池、佇列等配合 deferredresult 實現非同步處理。

根據官方描述,spring mvc 處理流程如下:

把 controller 返回的 deferredresult 儲存在記憶體佇列或集合當中;

spring mvc 呼叫 request.startasync(),開啟非同步;

dispatcherservlet 和所有的 filter 退出當前請求執行緒;

業務應用在非同步執行緒中設定 deferredresult 的返回值,spring mvc 會再次傳送請求;

dispatcherservlet 再次被呼叫,並使用 deferredresult 的返回值;

使用 callable 進行非同步處理與 deferredresult 類似。不同的是,callable 會交給系統指定的 taskexecutor 執行。

根據官方描述,spring mvc 處理流程如下:

controller 返回 callable;

spring mvc 呼叫 request.startasync(),開啟非同步,提交 callable 到乙個任務執行緒池;

dispatcherservlet 和所有的 filter 退出當前請求執行緒;

業務應用在非同步執行緒中返回值,spring mvc 會再次傳送請求;

dispatcherservlet 再次被呼叫,並使用 callable 的返回值;

public callableasync()

listenablefuture 作為返回值,與 deferredresult 類似。也需要使用者自行處理非同步執行緒,但不支援超時、完成**,需要自行處理。

public listenablefutureasync());

executors.newsinglethreadexecutor().submit(listenablefuture);

return listenablefuture;

}deferredresult 和 callable 都只能返回乙個非同步值。如果需要返回多個物件,就要使用 responsebodyemitter。返回的每個物件都會被 httpmessageconverter 處理並寫回輸出流。如果希望設定更多返回資料,如 header、status 等,可以把 responsebodyemitter 作為 responseentity 的實體資料返回。

public responsebodyemitter responsebodyemitter() catch (exception ignore) {}

});return responsebodyemitter;

}如果希望跳過返回值的自動轉換,直接把輸出流寫入 outputstream,可以使用 streamingresponsebody。也可以作為 responseentity 的實體資料返回。

public streamingresponsebody streamingresponsebody() catch (ioexception ignore) {}

});};

return streamingresponsebody;

}以上幾種非同步處理方式各有差異,需要按需取捨。對比如下。

可返回次數

資料轉換

**執行緒池

deferredresult

1 次有

完成、超時

自行處理

callable

1 次有

無系統處理

listenablefuture

1 次有

無自行處理

responsebodyemitter多次有

無自行處理

streamingresponsebody多次無

無自行處理

推薦閱讀

linux cron 定時任務

人類簡史、軟體架構和中颱

限流演算法探秘

git 工作原理

mybatis 一級二級和自定義快取

springmvc使用非同步處理請求

同步請求圖示 同步處理的圖示如上 http請求,tomcat 或其他中介軟體會有乙個相應的執行緒來處理這個 請求,所有的業務邏輯都會在這個執行緒裡去執行,最後返回 響應。但是 tomcat 等中介軟體,它們可以管理的執行緒數是有限的,當數量達到一定程度之後,再有請求進入,會被阻塞掉。簡單非同步圖示 ...

springmvc 5 資料的處理

1.提交資料的處理 a 提交的網域名稱稱和提交的引數一致即可 b 如果網域名稱稱和提交的引數名不一致 如果uname沒有被轉過來,將會報錯 c 如果提交的是乙個物件 提交的網域名稱和物件的屬性名一致,處理器的引數使用對應的物件即可 這樣寫的前提條件是user必須有乙個預設構造器,就是無參構造器,否則...

SpringMVC 非同步功能

假設某個請求需要耗費大量的時間,那麼,該請求的執行緒就會一直同步等待該次請求完成,才能被返回執行緒池,分配給下乙個新的請求,這樣極大的限制了系統的處理能力.所以我們希望能在controller層的方法中非同步執行,另起乙個執行緒去處理耗時任務,讓該執行緒先返回執行緒池,那麼它就可以繼續處理下乙個請求...