스프링 부트 - 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.java
1
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.java
1
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/