티스토리 뷰

현상 

서버에서 rest api 사용 history를 트래킹 하기 위해 아래와 같이 사용하고 있었다.

@Component
public class HttpInterceptor implements AsyncHandlerInterceptor {

    final Logger L = LoggerFactory.getLogger(this.getClass());

    @Autowired
    RestHistoryService restHistoryService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (!"OPTIONS".equals(request.getMethod()) && URL.contains(Const.REST_URL)) {
        	// 여기서 rest 관련 정보 history create
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (response.getStatus() != 200) {
        	// 여기서 실패 history update
        }
    }

    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    }

}

 

그리고 WebMvcConfigurer에서 interceptor 를 추가함 (여기서 rest 패턴만 따로 빼도 됨)

@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer {

    @Autowired
    HttpInterceptor httpInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(httpInterceptor).addPathPatterns("/**/**");
    }
}	

 

잘 사용하고 있었는데 이슈가..

RestHistory가 두개씩 쌓이는 현상이 발생했다. (사내 데이터라 캡쳐못함)

처음엔 연속적으로 요청이 온다고 생각했는데 Debugging 해보니까 preHandle을 두번 타는걸 확인.

 

 

원인은?

DeferredResult 로 응답을 주는 API가 추가 됐었는데, AsyncHandlerInterceptor는 Async로 동작했을 때 Interceptor의 flow가 다르다. (Callable같은 Async Response 다 포함)

 

※ 참고 : www.logicbig.com/tutorials/spring-framework/spring-web-mvc/async-intercept.html

 

Spring MVC - Intercepting Async Requests using AsyncHandlerInterceptor

Spring MVC - Intercepting Async Requests using AsyncHandlerInterceptor [Last Updated: Feb 13, 2018]

www.logicbig.com

위 링크를 참고해보면 interceptor가 아래와 같은 흐름으로 동작한다.

preHandle -> afterConcurrentHandlingStarted -> preHandle -> postHandle -> afterCompletion

기존에 preHandle 들어올 때마다 history를 저장하고 있으니 Async 처리될 때는 두번씩 찍힌거다. 

 

해결은

위 링크에서는 Async의 흐름이 다르니 아래와 같이 구분하라는 뜻이었다.

Within interceptor, to distinguish between the initial request and the subsequent dispatch after asynchronous handling completes, interceptors can check whether the javax.servlet.DispatcherType returns from ServletRequest#getDispatcherType() call is "REQUEST" or "ASYNC".

 

이력은 어떤 요청이 왔는지 체크하기 위해서니까 아래와 같이 preHandle에서 REQUEST 타입일 때만 남기기로 함

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (DispatcherType.REQUEST.equals(request.getDispatcherType())) {
        	// REQUEST 타입 일때만 이력 남김
        }
        return true;
    }
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함