SpringBoot では、HandlerInterceptorAdapter アダプターを使用して独自のインターセプターを実装できます。このようにして、すべてのリクエストをインターセプトし、それに応じて処理することができます。
アプリケーションシナリオ
- ロギングでは、情報監視や情報統計などのリクエスト情報のログを記録できます。
- 権限チェック: ログイン検出など、プロセッサに入ってログインしているかどうかを確認し、ログインしていない場合はログイン ページに直接戻ります。
- パフォーマンスの監視: 通常、ログが遅くなります。
HandlerInterceptorAdapter では主に次のメソッドが提供されます。
- preHandle: メソッドが呼び出される前に実行されます。この方法では、検証と同様の機能を実行できます。true が返された場合は、次のインターセプターの呼び出しを続けます。false が返された場合、実行は中断されます。つまり、呼び出したいメソッドは実行されませんが、必要な応答に応答を変更できます。
- postHandle: メソッドの実行後に呼び出されます。
- afterCompletion: リクエスト全体が処理された後、つまりビューがレンダリングされた後、または呼び出し元が応答を受信した後のコールバック。
ハンドラーインターセプター
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
AsyncHandlerInterceptor
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
default void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
}
抽象クラス HandlerInterceptorAdapter
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
public HandlerInterceptorAdapter() {
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
}
}
これら 3 つのクラスとインターフェイスの関係を見ると、HandlerInterceptorAdapter を統合することで、必要なメソッドだけを書き換えられるようにするだけであることがわかります。すべてを書き換える必要がある場合は、インターフェイスを直接実装することもできます。
実行プロセスは次のように要約されます。
- インターセプターの実行順序は、Spring 構成ファイルで定義された順序によって決まります。
- すべてのインターセプタの preHandle メソッドは return false になるまで順番に実行されます。たとえば、2 番目の preHandle メソッドが return false の場合、3 番目以降のインターセプタは実行されません。それらがすべて true を返す場合、preHandle メソッドは順番にロードされます。
- 次に、メイン メソッド (独自のコントローラ インターフェイス) を実行します。途中で例外がスローされた場合、結果は return false と同じになります。PostHandle は実行され続けませんが、afterCompletion メソッドは逆の順序で実行されます。
- main メソッドがビジネス ロジックの実行を完了した後 (ページはまだデータをレンダリングしていません)、postHandle メソッドが逆の順序で実行されます。3 番目のインターセプターの preHandle メソッドが false を返した場合、2 番目と最初の postHandle メソッドと afterCompletion が実行されます (これは postHandle が実行された後、つまりページがデータをレンダリングした後、クリーンアップのために実行されるだけです)作業を開始します))方法。(postHandleとafterCompletionは逆の順序で実行されます)
インターセプタを書く
public class LoginInterceptor extends HandlerInterceptorAdapter {
Logger logger = LoggerFactory.getLogger(getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==============LoginInterceptor========preHandle==========");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("==============LoginInterceptor======postHandle============");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("==============LoginInterceptor=======afterCompletion===========");
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==============LoginInterceptor========afterConcurrentHandlingStarted==========");
}
}
public class LoginInterceptor2 extends HandlerInterceptorAdapter {
Logger logger = LoggerFactory.getLogger(getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==============LoginInterceptor2========preHandle==========");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("==============LoginInterceptor2======postHandle============");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("==============LoginInterceptor2=======afterCompletion===========");
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==============LoginInterceptor2========afterConcurrentHandlingStarted==========");
}
}
WebMvcConfigurerAdapter 抽象クラスは、WebMvcConfigurer インターフェイスの単純な抽象化 (いくつかのデフォルト実装を追加) ですが、WebMvcConfigurerAdapter は Spring Boot 2.0 および Spring 5.0 で廃止されました。WebMvcConfigurer を直接実装するか、WebMvcConfigurationSupport を直接継承することが公式に推奨されています
WebMvcConfigurer 構成インターセプターを実装する
@Configuration
public class SpringMVCConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor());
registry.addInterceptor(new LoginInterceptor2());
}
}
上記の「操作プロセスの概要」でご自身で確認してください。詳しくは説明しません。