前段時間研究了下 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層的方法中非同步執行,另起乙個執行緒去處理耗時任務,讓該執行緒先返回執行緒池,那麼它就可以繼續處理下乙個請求...