스프링 부트 - HandlerInterceptor
Interceptor는 말 그대로 가로채는 것을 의미한다. 예를 들어, 세션 검증이나 로그 처리 같은 기능을 수행하기 위해 특정 url에 요청이 들어오면 그 요청을 가로채 특정한 작업을 수행하는 기능이다.
현재 진행중인 프로젝트에 알림 기능이 있는데, 알림이 존재하는 경우에 알림이 있다는 표시를 해주기 위해 view에
hasNotification이라는 모델을 넘겨주고자 한다. 이 작업을 모든 요청에 적용하기 위해서 Interceptor를 적용할 것이다.Interceptor는
HandlerInterceptor인터페이스를 구현하여 만들 수 있다.HandlerInterceptor의 메서드는 아래의 세 가지가 있다.- boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
Controller실행 직전에 동작을 하며, 반환 값에 따라 진행 여부를 결정한다.
- void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
Conroller진입 후 view가 렌더링 되기 전에 수행을 한다.modelAndView를 사용하여model에 데이터를 추가하는 조작이 가능하다.
- void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
Conroller진입 후 view가 렌더링 된 이후에 마지막으로 실행이 되는 메서드이다.
- boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
나는 핸들러 처리 이후 뷰가 렌더링 되기 전에 알림 여부를 가지는 모델을 추가해주기 위해
postHandle메서드를 구현하였다.NotificationInterceptor.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class NotificationInterceptor implements HandlerInterceptor {
private final NotificationRepository notificationRepository;
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 뷰 렌더링 전, 핸들러 처리 이후
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (modelAndView != null && !isRedirectView(modelAndView) && authentication != null && authentication.getPrincipal() instanceof UserAccount) {
Account account = ((UserAccount)authentication.getPrincipal()).getAccount();
long count = notificationRepository.countByAccount(account);
modelAndView.addObject("hasNotification", count > 0); // 알람이 있는 경우 true, 없으면 false
}
}
private boolean isRedirectView(ModelAndView modelAndView) { // 리다이렉트 요청인지 확인하는 메서드
// 뷰의 이름이 redirect: 로 시작하거나, RedirectView 타입인 경우
return modelAndView.getViewName().startsWith("redirect:") || modelAndView.getView() instanceof RedirectView;
}
}로그인된 사용자에게 적용하고 리다이렉트 요청에는 적용하지 않기 위해
인증 객체를 가져와
modelAndView를 사용하고,RedirectView가 아닌 경우, 인증 정보가 있고principal이UserAccount타입일 때 적용한다.principal안에 들어있는 객체를UserAccount로 형변환하여account객체를 가져와 해당 사용자의 알림 개수를 구한다.알림이 있는 경우 true, 없는 경우 false를 모델에 넣어준다.
HandlerInterceptor 적용하기
이제 작성한
HandlerInterceptor를 실제로 적용하기 위한 설정을 해주어야 한다.WebMvcConfigurer를 구현한 클래스를 작성하여addInterceptors메서드에 해당 인터셉터를 등록하면 된다.WebConfig.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//@EnableWebMvc : 이 설정을 주면 스프링 부트가 제공하는 웹mvc 자동설정을 사용하지 않는다는 뜻.
// 지금은 추가설정만 하는 것
public class WebConfig implements WebMvcConfigurer {
private final NotificationInterceptor notificationInterceptor;
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(notificationInterceptor)
.excludePathPatterns('url패턴 추가'); // 인터셉터를 적용하지 않을 url 패턴
}
}excludePathPatterns()에 추가한 url패턴에는 인터셉터를 적용하지 않도록 설정할 수 있다.- 예를들어,
/css/**,/js/**등과 같은static리소스들에 적용하고 싶지 않은 경우에 추가할 수 있다. - String 배열이나 리스트 타입으로 넣어줄 수 있다.
- 예를들어,
참조
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1/dashboard
https://elfinlas.github.io/2017/12/28/SpringBootInterceptor/