ハンドラーインターセプターを使用したSpringモデルパラメーターの変更
1. 序章
このチュートリアルでは、SpringMVCに焦点を当てます
HandlerInterceptorの基本について知りたい場合は、この記事をチェックしてください。
2. Mavenの依存関係
Interceptors を使用するには、pom.xmlファイルのdependenciesセクションに次のセクションを含める必要があります。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.13</version>
</dependency>
最新バージョンはここにあります。
この依存関係はSpringWebのみを対象としているため、完全なWebアプリケーション用のs pring-coreとspring-context、および選択したログライブラリを追加することを忘れないでください。
3. カスタム実装
HandlerInterceptor のユースケースの1つは、モデルに共通/ユーザー固有のパラメーターを追加することです。これは、生成された各ビューで使用できます。
この例では、カスタムインターセプターの実装を使用して、ログに記録されたユーザーのユーザー名をモデルパラメーターに追加します。 より複雑なシステムでは、ユーザーのアバターパス、ユーザーの場所など、より具体的な情報を追加する場合があります。
新しいInterceptorクラスの定義から始めましょう。
public class UserInterceptor extends HandlerInterceptorAdapter {
private static Logger log = LoggerFactory.getLogger(UserInterceptor.class);
...
}
HandlerInterceptorAdapter を拡張します。これは、 preHandle()および postHandle()メソッドのみを実装するためです。
前述したように、ログに記録されたユーザーの名前をモデルに追加します。 まず、ユーザーがログインしているかどうかを確認する必要があります。 SecurityContextHolder をチェックすることで、この情報を取得できます。
public static boolean isUserLogged() {
try {
return !SecurityContextHolder.getContext().getAuthentication()
.getName().equals("anonymousUser");
} catch (Exception e) {
return false;
}
}
HttpSession が確立されているが、誰もログインしていない場合、SpringSecurityコンテキストのユーザー名はanonymousUserになります。 次に、 preHandle():の実装に進みます。
3.1. メソッドpreHandle()
リクエストを処理する前に、モデルパラメータにアクセスすることはできません。 ユーザー名を追加するには、HttpSessionを使用してパラメーターを設定する必要があります。
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object object) throws Exception {
if (isUserLogged()) {
addToModelUserDetails(request.getSession());
}
return true;
}
リクエストを処理する前にこの情報の一部を使用している場合、これは非常に重要です。 ご覧のとおり、ユーザーがログインしているかどうかを確認し、セッションを取得してリクエストにパラメータを追加しています。
private void addToModelUserDetails(HttpSession session) {
log.info("=============== addToModelUserDetails =========================");
String loggedUsername
= SecurityContextHolder.getContext().getAuthentication().getName();
session.setAttribute("username", loggedUsername);
log.info("user(" + loggedUsername + ") session : " + session);
log.info("=============== addToModelUserDetails =========================");
}
SecurityContextHolder を使用して、loggedUsernameを取得しました。 Spring Security UserDetails の実装をオーバーライドして、標準のユーザー名の代わりに電子メールを取得できます。
3.2. メソッドpostHandle()
リクエストを処理した後、モデルパラメータが利用可能になるため、値を変更したり、新しい値を追加したりするためにそれらにアクセスする場合があります。 これを行うには、オーバーライドされた postHandle()メソッドを使用します。
@Override
public void postHandle(
HttpServletRequest req,
HttpServletResponse res,
Object o,
ModelAndView model) throws Exception {
if (model != null && !isRedirectView(model)) {
if (isUserLogged()) {
addToModelUserDetails(model);
}
}
}
実装の詳細を見てみましょう。
まず、モデルがnullでないかどうかを確認することをお勧めします。NullPointerExceptionが発生するのを防ぎます。
さらに、ViewがRedirectViewのインスタンスではないかどうかを確認する場合があります。
リクエストが処理されてリダイレクトされた後、パラメータを追加/変更する必要はありません。すぐに、新しいコントローラが処理を再度実行するためです。 ビューがリダイレクトされているかどうかを確認するために、次の方法を導入しています。
public static boolean isRedirectView(ModelAndView mv) {
String viewName = mv.getViewName();
if (viewName.startsWith("redirect:/")) {
return true;
}
View view = mv.getView();
return (view != null && view instanceof SmartView
&& ((SmartView) view).isRedirectView());
}
最後に、ユーザーがログに記録されているかどうかを再度確認し、記録されている場合は、Springモデルにパラメーターを追加します。
private void addToModelUserDetails(ModelAndView model) {
log.info("=============== addToModelUserDetails =========================");
String loggedUsername = SecurityContextHolder.getContext()
.getAuthentication().getName();
model.addObject("loggedUsername", loggedUsername);
log.trace("session : " + model.getModel());
log.info("=============== addToModelUserDetails =========================");
}
このロジックはアプリケーションの「舞台裏」で機能するため、ロギングは非常に重要であることに注意してください。 View ごとに、適切にログを記録せずにいくつかのモデルパラメータを変更していることを忘れがちです。
4. 構成
新しく作成したInterceptorをSpring構成に追加するには、 WebMvcConfigurer:を実装する WebConfigクラス内のaddInterceptors()メソッドをオーバーライドする必要があります。
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInterceptor());
}
XML Spring構成ファイルを編集することで、同じ構成を実現できます。
<mvc:interceptors>
<bean id="userInterceptor" class="com.baeldung.web.interceptor.UserInterceptor"/>
</mvc:interceptors>
この時点から、生成されたすべてのビューのすべてのユーザー関連パラメーターにアクセスできるようになります。
複数のSpringInterceptors が構成されている場合、 preHandle()メソッドは構成順に実行されますが、 postHandle()および afterCompletion( )メソッドは逆の順序で呼び出されます。
5. 結論
このチュートリアルでは、ユーザー情報を提供するためにSpringMVCのHandlerInterceptorを使用してWebリクエストをインターセプトする方法について説明します。
この特定の例では、Webアプリケーションに記録されたユーザーの詳細をモデルパラメーターに追加することに焦点を当てました。 このHandlerInterceptorの実装を拡張するには、より詳細な情報を追加します。
すべての例と構成は、ここGitHubで入手できます。
5.1. シリーズの記事
シリーズのすべての記事:
- SpringMVCハンドラーインターセプターの概要
- ハンドラーインターセプターを使用したSpringモデルパラメーターの変更(これ)