この記事では、主にSpringMVC非同期処理の5つの方法を紹介します。この記事では、すべての人の研究や仕事のための特定の参照値を持つサンプルコードを通じて詳細に紹介します。それを必要とする友人は参照できます。
先ほど、ダイヤモンドの原理を学びましたが、重要な知識のひとつは、サーブレットの非同期処理を利用したロングコネクションの実現です。非同期処理の最大の利点は、現在のスレッドをブロックすることなく同時実行の量を増やすことができることです。実際、Spring MVCは非同期処理もサポートしています。この記事では、関連する技術的なポイントを記録します。
非同期処理のデモ
非同期リターンを有効にする場合は、@ EnableAsyncをオンにする必要があります。次のコードでは、DeferredResultが非同期処理に使用されています。
リクエストが届いたら、最初にDeferredResultオブジェクトを作成し、タイムアウト期間を60秒に設定します。次に、非同期完了および待機タイムアウト時のDeferredResultのコールバックを指定します。同期処理では、非同期処理を作成してから、DeferredResultを返すだけで済みます。このように、Spring MVCが要求を処理した後、クライアントに応答をすぐに返すことはなく、DeferredResultの完了を待ちます。DeferredResultが60秒以内に処理されない場合、タイムアウトがトリガーされ、応答がクライアントに返されます。
@RequestMapping(value = "/async/demo")
public DeferredResult<String> async(){
// 创建 DeferredResult,设置超时时间 60s
DeferredResult<String> deferredResult = new DeferredResult<>((long)60 * 1000);
String uuid = UUID.randomUUID().toString();
Runnable callback = () -> manager.remove(deferredResult, uuid);
// 设置完成和超时的回调
deferredResult.onCompletion(callback);
deferredResult.onTimeout(callback);
// 创建异步任务
manager.addAsyncTask(deferredResult, uuid);
// 同步返回 DeferredResult
return deferredResult;
}
非同期タスクの場合、DeferredResultオブジェクトを保持する必要があります。非同期処理の最後に、DeferredResult.setResultを手動で呼び出して出力を完了する必要があります。setResultを呼び出すと、データ出力がクライアントに書き込まれ、非同期完了イベントがトリガーされてコールバックが実行されます。
task.getDeferredResult().setResult(ConfigJsonUtils.toJsonString(map));
非同期処理にDeferredResultを使用する
DeferredResultこのクラスは、遅延した結果を表します。DeferredResultは非同期タスクで使用でき、他のスレッドはDeferredResultを取得して、DeferredResultの戻りデータを設定できます。通常、スレッドプール、キューなどを使用してDeferredResultと連携し、非同期処理を実現できます。
公式の説明によると、SpringMVCの処理フローは次のとおりです。
1.コントローラーから返されたDeferredResultをメモリキューまたはコレクションに保存します
。2。SpringMVCがrequest.startAsync()を呼び出して非同期を有効にします。3。DispatcherServlet
とすべてのフィルターが現在のリクエストスレッドを終了します
。4。ビジネスアプリケーションが非同期スレッドDeferredResultの戻り値の場合、SpringMVCは要求を
再度送信します; 5。DispatcherServletが再度呼び出され、DeferredResultの戻り値が使用されます。
非同期処理にCallableを使用する
非同期処理にCallableを使用することは、DeferredResultに似ています。違いは、Callableが実行のためにシステムによって指定されたTaskExecutorに引き渡されることです。
公式の説明によると、SpringMVCの処理フローは次のとおりです。
1.コントローラーがCallableを返します。2。SpringMVC
がrequest.startAsync()を呼び出して非同期をオンにし、Callableをタスクスレッドプールに送信します。3。DispatcherServlet
とすべてのフィルターが現在のリクエストスレッドを終了します
。4。ビジネスアプリケーションが戻ります。非同期スレッドの値であるSpringMVCは、リクエストを再度送信し
ます。5。DispatcherServletが再度呼び出され、Callableの戻り値が使用されます。
@RequestMapping(value = "/async/demo")
public Callable<String> async(){
Callable<String> callable = () -> String.valueOf(System.currentTimeMillis());
// 同步返回
return callable;
}
非同期処理にListenableFutureを使用する
DeferredResultと同様に、戻り値としてListenableFuture。ユーザーも非同期スレッドを自分で処理する必要がありますが、タイムアウトと完了コールバックはサポートされておらず、自分で処理する必要があります。
@RequestMapping(value = "/async/demo")
public ListenableFuture<String> async(){
ListenableFutureTask<String> ListenableFuture= new ListenableFutureTask<>(() -> {
return String.valueOf(System.currentTimeMillis());
});
Executors.newSingleThreadExecutor().submit(ListenableFuture);
return ListenableFuture;
}
非同期処理にResponseBodyEmitterを使用する
DeferredResultとCallableはどちらも、非同期値のみを返すことができます。複数のオブジェクトを返す必要がある場合は、ResponseBodyEmitterを使用してください。返された各オブジェクトはHttpMessageConverterによって処理され、出力ストリームに書き戻されます。ヘッダーやステータスなど、より多くの戻りデータを設定する場合は、ResponseBodyEmitterをResponseEntityのエンティティデータとして返すことができます。
@RequestMapping("/async/responseBodyEmitter")
public ResponseBodyEmitter responseBodyEmitter(){
ResponseBodyEmitter responseBodyEmitter=new ResponseBodyEmitter();
Executors.newSingleThreadExecutor().submit(() -> {
try {
responseBodyEmitter.send("demo");
responseBodyEmitter.send("test");
responseBodyEmitter.complete();
} catch (Exception ignore) {}
});
return responseBodyEmitter;
}
非同期処理にStreamingResponseBodyを使用する
戻り値の自動変換をスキップして、出力ストリームをOutputStreamに直接書き込む場合は、StreamingResponseBodyを使用できます。ResponseEntityのエンティティデータとして返すこともできます。
@RequestMapping("/async/streamingResponseBody")
public StreamingResponseBody streamingResponseBody(){
StreamingResponseBody streamingResponseBody = outputStream -> {
Executors.newSingleThreadExecutor().submit(() -> {
try {
outputStream.write("<html>streamingResponseBody</html>".getBytes());
} catch (IOException ignore) {}
});
};
return streamingResponseBody;
}
各種加工方法の比較