2017-03-01 4 views
4

メソッドがCompletionStageを返すときにフィルタが2回実行されていたという問題が発生しました。 RequestMappinghere)のドキュメントからは、サポートされている戻り値です。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"; 
    }; 
} 

だから、私はかなりいくつかのことについて不明な点です。

  1. CallableCompletionStageは、それがで実行されるスレッドのコンテキストで異なる扱いをされていることが表示されます。
  2. その場合は、なぜ私のフィルタは、それぞれの場合に二回実行されていますか?フィルタのジョブが特定のリクエスト固有のコンテキストを設定する場合は、とにかくアクセスできない場合はCompletionStageのために再度実行するのは意味がありません。
  3. なぜフィルタが2回実行されるのですか?

答えて

2

OncePerRequestFilterに置き換えてください。GenericFilterBean

関連する問題