Spring Handler Interceptor
Simply put, a Spring interceptor is a class that either extends the HandlerInterceptorAdapter class or implements the HandlerInterceptor interface.
public class LoggerInterceptor implements HandlerInterceptor {
...
}
Spring Interceptor는
①HandlerInterceptor 인터페이스를 구현 하거나,
②HandlerInterceptorAdapter 클래스를 상속 하는 클래스다.
①HandlerInterceptor 인터페이스를 구현
HandlerInterceptor 에는 3가지 메인 메서드가 있으며, HandlerInterceptor 인터페이스를 구현하기 위해서는 이 세가지 메서드를 구현해야 한다.
- prehandle() – called before the execution of the actual handler
- postHandle() – called after the handler is executed
- afterCompletion() – called after the complete request is finished and the view is generated
1. preHandle()
이름에서 알 수 있듯이 요청을 처리하기 전에 preHandle()을 호출한다.
리턴값은 boolean으로, true / false 값을 리턴하도록 되어 있다.
"각 메서드의 반환값이 true이면 핸들러의 다음 체인이 실행되지만 false이면 중단하고 남은 인터셉터와 컨트롤러가 실행되지 않습니다."
기본적으로 이 메서드는 true를 반환하지만, 처리에 따라 false를 반환해서 Spring에게 로직 수행을 중단하라고 말할 수 있다. 사용의 예시로는 request parameter에 대한 로그 정보를 남길 수 있는데, simple Log4J logger를 사용하여 커스텀화 해서 사용하는 예시가 있다.
public class TestInterceptor implements HandlerInterceptor {
// controller로 보내기 전에 처리하는 인터셉터
// 반환이 false라면 controller로 요청을 안함
// 매개변수 Object는 핸들러 정보를 의미한다. ( RequestMapping , DefaultServletHandler )
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response
, Object handler) throws Exception {
// your code
System.out.println("컨트롤러의 메서드가 실행되기 전에 실행됨");
log.info("[preHandle][" + request + "]" + "[" + request.getMethod() + "]" + request.getRequestURI() + getParameters(request));
// 로그인 여부 확인 용도
HttpSession session = request.getSession();
String requestUrl = request.getRequestURI().toString();
if (requestUrl.contains("/resources/")) { // 리소스 경로 제외
} else if (requestUrl.contains("/api/")) {
String mbrNo = (String) session.getAttribute("sess_mbrNo");
if (mbrNo != null) {
String ori_mbrNo = session.getAttribute("_hdn_mbrNo_").toString();
if (!mbrNo.equals(ori_mbrNo)) {
System.out.println("로그인 세션 회원 번호 불일치 : mbrNo [" + mbrNo + "] ori_mbrNo >" + ori_mbrNo);
response.sendRedirect("/common/logout");
return false;
}
}
} else if (requestUrl.contains("/common/test")) {
// 특정 url 처리
// your code
} else {
// 로그인 체크하여 로그인 페이지로 이동 처리
String webId = (String) session.getAttribute("sess_webId");
if (webId == null) {
response.sendRedirect("/signin/login?call_back_url=" + requestUrl);
return false;
}
}
return true;
}
}
2. postHandle()
인터셉터는 요청을 처리한 후 DispatcherServlet이 View를 생성(렌더링)하기 전에 이 메서드를 호출합니다.
@Override
public void postHandle( HttpServletRequest request, HttpServletResponse response
, Object handler, ModelAndView modelAndView) throws Exception {
// your code
System.out.println("컨트롤러의 메서드가 실행된 후에 실행됨 ");
}
3. afterCompletion()
@Override
public void afterCompletion( HttpServletRequest request, HttpServletResponse response
, Object handler, Exception ex) {
// your code
if (ex != null){
ex.printStackTrace();
}
log.info("[afterCompletion][" + request + "][exception: " + ex + "]");
}
이제 모든 조각들을 합쳤으니 사용자 지정 interceptor를 추가해서 사용 가능 하다.
그러기 위해서는 addIntercepters() 메서드를 Override해야 한다:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggerInterceptor());
}
* 뷰 페이지에서는 로그인 버튼을 눌렀을 때 요청이 /user/login으로 요청이 갈 수 있도록 form을 다음과 같이 작성합니다.
<form method="post" action="${pageContext.servletContext.contextPath }/user/login">
* XML Spring 구성 파일을 편집하여 동일한 구성을 수행할 수 있다:
<mvc:interceptors>
<bean id="loggerInterceptor" class="com.baeldung.web.interceptor.LoggerInterceptor"/>
</mvc:interceptors>
= > 이 configuration을 활성화 하면, loggerInterceptor가 활성화 되고, 어플리케이션의 모든 요청이 올바르게 기록된다.
* 혹은, 특정 경로로 요청이 왔을때 사용하고 싶은 interceptor를 매칭시킬 수도 있다.
<mvc:interceptor>
<!-- /user/login 경로인 경우 AuthLoginInterceptor 객체의 preHandle() 메서드 실행 -->
<mvc:mapping path="/user/login" />
<bean class="com.victolee.security.AuthLoginInterceptor" />
</mvc:interceptor>
② HandlerInterceptorAdapter 클래스를 상속 받아 구현
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response,
Object obj) throws Exception {
System.out.println("MyInterCeptor - preHandle");
return true;
}
}
HandlerInterceptorAdapter 클래스를 상속 받으면, postHandle() , afterCompletion() 메서드가 구현되어 있으므로 필요한 메서드만 오버라이딩 하면 됩니다.
Spring 인터셉터가 여러 개 구성된 경우 preHandle() 메서드는 구성 순서대로 실행되고 postHandle() 및 afterCompletion() 메서드는 역순으로 호출된다.
https://www.baeldung.com/spring-mvc-handlerinterceptor
https://victorydntmd.tistory.com/176
[Spring] Interceptor (1) - 개념 및 예제
인터셉터 ( Interceptor )Interceptor란 컨트롤러에 들어오는 요청 HttpRequest와 컨트롤러가 응답하는 HttpResponse를 가로채는 역할을 합니다.인터셉터는 관리자만 접근할 수 있는 관리자 페이지에 접근하
victorydntmd.tistory.com
'BackEnd > Spring' 카테고리의 다른 글
[Spring] Quartz 를 통한 스케줄링 등록 (0) | 2024.09.03 |
---|---|
@Value 애너테이션이 property 값을 null로 받아오는경우 (0) | 2024.08.14 |
[Spring] com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class 오류 해결 (0) | 2023.02.28 |
MVC 패턴, Dispatcher-Servlet 정리 (0) | 2023.01.05 |
[SPRING] @RequestBody / @ResponseBody / Jackson2HttpMessageConverter (0) | 2022.10.26 |