メソッドがCompletionStage
を返すときにフィルタが2回実行されていたという問題が発生しました。 RequestMapping
(here)のドキュメントからは、サポートされている戻り値です。CompletionStageを返す要求に対してSpringブートが2回フィルタを実行します
Callableを返す代わりに、アプリケーションが独自に選択した別のスレッドで戻り値を生成するために使用するCompletionStage(CompletableFutureなどで実装されます)。
プロジェクトは非常に複雑なので、私は新しい単純なスプリングブートプロジェクトを作成しました。これは、その中に(のみ)コントローラです:
@Controller
public class BaseController {
@RequestMapping("/hello")
@ResponseBody
public CompletionStage<String> world() {
return CompletableFuture.supplyAsync(() -> "Hello World");
}
}
とフィルタ:私はコールcurl http://localhost:8080/hello
を行うと
@WebFilter
@Component
public class GenericLoggingFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
System.out.println(httpServletRequest.getMethod() + " " +
httpServletRequest.getRequestURI());
chain.doFilter(request, response);
}
}
、それはコンソール上で二回GET /hello
を印刷します。私は返すように、コントローラのメソッドを変更するとString
は:
@RequestMapping("/hello")
@ResponseBody
public String world() {
return "Hello World";
}
それは一度だけ、それを印刷します。この動作は、実際の並行処理の意味がないCallable
に変更した場合でも表示されます(もちろん、スプリング自体がこれをAsync
リクエストとして処理している可能性があります)。春が使用可能な要求コンテキストを持って再びウェブ全体スタックを実行している場合は、次のため
そう、でもそれは本当に意味がありません。IllegalStateException: No thread-bound request found...
@RequestMapping("/hello")
@ResponseBody
public CompletionStage<String> world() {
return CompletableFuture.supplyAsync(() -> {
System.out.println(RequestContextHolder.currentRequestAttributes());
return "Hello World";
});
}
は、例外がスローされます驚くべきことである何
には、次の作品ということ、である:
@RequestMapping("/hello")
@ResponseBody
public Callable<String> world() {
return() -> {
System.out.println(RequestContextHolder.currentRequestAttributes());
return "Hello World";
};
}
だから、私はかなりいくつかのことについて不明な点です。
Callable
とCompletionStage
は、それがで実行されるスレッドのコンテキストで異なる扱いをされていることが表示されます。- その場合は、なぜ私のフィルタは、それぞれの場合に二回実行されていますか?フィルタのジョブが特定のリクエスト固有のコンテキストを設定する場合は、とにかくアクセスできない場合は
CompletionStage
のために再度実行するのは意味がありません。 - なぜフィルタが2回実行されるのですか?