私はSpring Boot Webアプリケーションで長時間実行しています。 これは、それがどのように動作するかです:未来をHTTPリクエスト間で利用できる安全な方法は何ですか?
- ユーザーがボタンをクリックすると、
POST
要求が行われ、運転が開始されます。 - 操作に時間がかかるため、非同期で開始され、すぐに応答が送信されます。
- JavaScriptを使用して、私は定期的に
GET
リクエストを送信して、操作が完了したかどうかを調べます。ここ
要求ハンドラである:
import java.util.concurrent.Future;
@RequestMapping(value = "/start", method = RequestMethod.POST)
@ResponseBody
String start(HttpSession session) {
Future<String> result = resultService.result();
session.setAttribute("result", result);
return "started";
}
@RequestMapping(value = "/status")
@ResponseBody
String status(HttpSession session) throws Exception {
@SuppressWarnings("unchecked")
Future<String> result = (Future<String>) session.getAttribute("result");
if (result != null && result.isDone()) {
return result.get();
} else {
return "working";
}
}
これは(別豆で)実行時間の長い操作である:
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
@Async
@Override
public Future<String> result() {
String result = computeResult(); // takes long
return new AsyncResult<String>(result);
}
完全な例はon GitHubあります。 また、それはどのように動作するかを示すa GIFです。今
、これは動作しますが、問題はSonarQubeが問題を提起したということです。
を「未来」とそのパラメータがシリアライズ可能またはセッションに保管しないでください。
これは、サーバーが「不動態化」と呼ばれるプロセスで、メモリ使用量を管理して
セッションは[...]、とにかくディスクに書き込むことができると説明しました。さらに、一部のサーバは、シャットダウン時にアクティブなセッションを自動的にファイルに書き出します。&は、起動時にそのようなセッションを非直列化します。
は、参照してくださいMITRE, CWE-579 - J2EEバッドプラクティス:私は要求間の長時間実行操作を追跡するためのより良い方法であるもの、
Future
はシリアライズすることはできませんので、セッション
に保存されている非直列化可能なオブジェクト?
今
この操作を起動時に「デシリアライズ」するか、再開しますか?そうであれば、操作の状態を保存してセッションに保存する方法を考えなければなりません。おそらくその状態クラスにFutureを実装する必要があります。そうでなければ、セッションに新しいクラスを格納するだけです。これは一時的なFutureフィールドを含んでいます。私はSpringMVCに精通していないので、これを行うより良い方法があれば驚くことはありません。 –
私のソリューションは、私が今アクセスできない、DeferredResultとListenableFutureを使用しています。これらのキーワードを使用して私が使ったチュートリアルを見つけることができるかもしれません。 – Tim