Spring Interceptor

- Springベースのアプリケーションを開発中であれば、Spring Interceptorを使用する方が、Servlet Filterを使用するよりも統合性の面でより良い。
- URLパターンをさらに細かく設定でき、Servlet FilterのdoFilterよりさらに細かくpreHandle、postHandle、afterCompletionメソッドを設定できるという長所がある。

| preHandle | Controller 呼び出し前、応答値がfalseであれば、それ以上進行しない。 |
| --- | --- |
| postHandle | Controller 呼び出し後、Controlle で例外が発生すると呼び出されない。 |
| afterCompletion | ビューがレンダリングされた後、例外が発生しても常に呼び出し、例外が発生した場合、どのような例外が発生したのかログを出力できる |

- どのControllerが呼び出されるのか、呼び出し情報も受け取ることができる。
- どのmodel AndViewが返されるのか、応答情報も受け取ることができる。


:::note warn
以下の例はログインに関するものもありますが、GoogleログインもFilterで処理していて、セキュリティに関してはFilterで扱うということで.. おそらく他のものでInterceptorを使うことになりそうだ。
:::

```java

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
            // addPathPatterns, excludePathPatternsなどを使って、
            // より細かくUrlパターンを指定することができる。
		    registry.addInterceptor(new LogInterceptor())
            .order(1)
            .addPathPatterns("/**")
            .excludePathPatterns("/css/**", "/*.ico", "/error");
        registry.addInterceptor(new LoginInterceptor())
						.order(2)
						.addPathPatterns("/**")
	          .excludePathPatterns("/user/loginForm","/user/signupForm","","/*.css", "/*.js", "/*.ico", "error");
    }

}
```
```java
@Slf4j
public class LogInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        String logId = UUID.randomUUID().toString();
        request.setAttribute(Constant.LOG_ID, logId);

        if(handler instanceof HandlerMethod){
            // 呼び出すControllerメソッドのすべての情報が含まれている。
            HandlerMethod hm = (HandlerMethod) handler;
        }

        log.info("REQUEST [{}] [{}] [{}]", logId, requestURI, handler);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        String logId = (String)request.getAttribute(Constant.LOGIN_ID);
        log.info("postHandle [{}]", modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String requestURI = request.getRequestURI();
        String logId = (String)request.getAttribute(Constant.LOGIN_ID);
        if(ex!=null){
            log.error("afterCompletion error", ex);
        }
        log.info("RESPONSE [{}] [{}] [{}]", logId, requestURI, handler);
    }
}
```
```java
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();

        log.info("認証チェック実行 {}", requestURI);

        HttpSession session = request.getSession(false);
        if (session == null || session.getAttribute(Constant.LOGIN_ID) == null) {
            log.info("未認証ユーザー");
            //ログインにRedirect
            response.sendRedirect("users/login?redirectURL=" + requestURI);
            return false;
        }

        return true;
    }

}
```