-
카테고리
-
세부 분야
백엔드
-
해결 여부
해결됨
인터셉터의 호출 순서 질문입니다.
23.02.16 16:41 작성 23.02.16 16:45 수정 조회수 477
1
강의를 따라가다 문득 preHandle
, postHandle
, afterCompletion
의 순서를 알고 싶어서 LoginCheckInterceptor 에 해당 메서드를 추가하여 로그를 찍어보았습니다.
질문은 맨 밑에 있으며, 코드는 이해를 돕기 위해 첨부했습니다.
LogInterceptor
@Slf4j
public class LogInterceptor implements HandlerInterceptor {
public static final String LOG_ID = "logId";
@Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler
) throws Exception {
String requestURI = request.getRequestURI();
String uuid = UUID.randomUUID().toString();
request.setAttribute(LOG_ID, uuid);
// @RequestMapping: HandlerMethod
// 정적 리소스: ResourceHttpRequestMethod
if (handler instanceof HandlerMethod) {
// 호출할 컨트롤러 메서드의 모든 정보가 포함되어 있다.
HandlerMethod hm = (HandlerMethod) handler;
}
log.info("[{}][{}] LogInterceptor preHandle", requestURI, uuid);
return true;
}
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView
) throws Exception {
String requestURI = request.getRequestURI();
String uuid = (String) request.getAttribute(LOG_ID);
log.info("[{}][{}] LogInterceptor postHandle", requestURI, uuid);
}
@Override
public void afterCompletion(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex
) throws Exception {
String requestURI = request.getRequestURI();
String uuid = (String) request.getAttribute(LOG_ID);
log.info("[{}][{}] LogInterceptor afterComplete", requestURI, uuid);
if (ex != null) {
log.error("LogInterceptor afterComplete Error: ", ex);
ex.printStackTrace();
}
}
}
LoginCheckInterceptor
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler
) throws Exception {
String requestURI = request.getRequestURI();
String uuid = (String) request.getAttribute(LogInterceptor.LOG_ID);
log.info("[{}][{}] LoginCheckInterceptor preHandle", requestURI, uuid);
HttpSession session = request.getSession();
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
log.info("미인증 사용자 요청 {}", requestURI);
response.sendRedirect("/login?redirectURL=" + requestURI);
return false;
}
return true;
}
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView
) throws Exception {
String requestURI = request.getRequestURI();
String uuid = (String) request.getAttribute(LogInterceptor.LOG_ID);
log.info("[{}][{}] LoginCheckInterceptor postHandle", requestURI, uuid);
}
@Override
public void afterCompletion(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex
) throws Exception {
String requestURI = request.getRequestURI();
String uuid = (String) request.getAttribute(LogInterceptor.LOG_ID);
log.info("[{}][{}] LoginCheckInterceptor afterCompletion", requestURI, uuid);
}
}
InterceptorConfig
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.order(1)
.addPathPatterns("/**") // 모두 허용
.excludePathPatterns("/css/**", "/*.ico", "/error"); // BlackList
registry.addInterceptor(new LoginCheckInterceptor())
.order(2)
.addPathPatterns("/**")
.excludePathPatterns(
"/", "/members/css", "/login",
"/logout", "/css/**", "*.ico", "/error"
);
}
}
결과 1 - 미인증 사용자 요청
// /items 요청
[/items][45e50a37-57a0-4298-b50e-e42141005426] LogInterceptor preHandle
[/items][45e50a37-57a0-4298-b50e-e42141005426] LoginCheckInterceptor preHandle
미인증 사용자 요청 /items
[/items][45e50a37-57a0-4298-b50e-e42141005426] LogInterceptor afterComplete
// Redirect - /login
[/login][18f052ab-b849-4690-83ec-43866660f570] LogInterceptor preHandle
[/login][18f052ab-b849-4690-83ec-43866660f570] LogInterceptor postHandle
[/login][18f052ab-b849-4690-83ec-43866660f570] LogInterceptor afterComplete
로그상으로 LoginCheckInterceptor
의 afterComplete
가 누락되었습니다.
결과2 - 정상 처리
// /login 요청
[/login][19bad338-e02d-4bbe-8b3a-5dfc55ad4428] LogInterceptor preHandle
LoginService: 'test', 'test!'
login? Member(id=1, loginId=test, name=테스터, password=test!)
[/login][19bad338-e02d-4bbe-8b3a-5dfc55ad4428] LogInterceptor postHandle
[/login][19bad338-e02d-4bbe-8b3a-5dfc55ad4428] LogInterceptor afterComplete
// Redirect - /items
[/items][679dc279-ff3a-4ee3-a424-26b18ac8dbbd] LogInterceptor preHandle
[/items][679dc279-ff3a-4ee3-a424-26b18ac8dbbd] LoginCheckInterceptor preHandle
[/items][679dc279-ff3a-4ee3-a424-26b18ac8dbbd] LoginCheckInterceptor postHandle
[/items][679dc279-ff3a-4ee3-a424-26b18ac8dbbd] LogInterceptor postHandle
[/items][679dc279-ff3a-4ee3-a424-26b18ac8dbbd] LoginCheckInterceptor afterCompletion
[/items][679dc279-ff3a-4ee3-a424-26b18ac8dbbd] LogInterceptor afterComplete
preHandle
은 order
의 순위대로 로그가 찍히는데, postHandle
과 afterCompletion
의 경우 order
의 순위와 반대로 호출이 됩니다.
혹시 위 2개의 결과에 대한 이유를 설명해주실 수 있을까요..? 그냥 로직때문에 그런 것인지 궁금합니다.
답변을 작성해보세요.
3
김영한
지식공유자2023.02.18
안녕하세요. 김회민님
생각해보시면 다음과 같이 동작합니다.
A 시작
B 시작
B 종료
A 종료
따라서 결과는 A시작 -> B 시작 -> B 종료 -> A 종료 순서가 됩니다.
감사합니다.
답변 1