250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- querydsl
- 동적sql
- 스프링 폼
- FetchType
- 지연로딩
- 즉시로딩
- PS
- shared lock
- 힙
- 다대다
- BOJ
- 낙관적락
- 다대일
- SQL프로그래밍
- 유니크제약조건
- 이진탐색
- fetch
- 데코레이터
- 일대다
- eager
- 백트래킹
- execute
- exclusive lock
- 비관적락
- 스토어드 프로시저
- dfs
- 연관관계
- CHECK OPTION
- 연결리스트
- JPQL
Archives
- Today
- Total
흰 스타렉스에서 내가 내리지
서블릿 예외 처리 - 필터, 인터셉터 본문
728x90
# 1. 필터와 DispatcherType
@Slf4j
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("log filter init!");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
String uuid = UUID.randomUUID().toString();
try{
log.info("REQUEST [{}][{}][{}]", uuid, request.getDispatcherType(), requestURI);
chain.doFilter(request, response);
}catch(Exception e){
throw e;
}finally {
log.info("RESPONSE [{}][{}][{}]", uuid, request.getDispatcherType(), requestURI);
}
}
@Override
public void destroy() {
log.info("log filter destroy");
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean logFilter(){
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/filter1", "/filter2");
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
return filterRegistrationBean;
}
}
이렇게만 하고 웹 서버를 켜면, /filter1, /filter2 경로에 대한 요청만 로그아 기록되는 것을 볼 수 있다.
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
→ 이렇게 두 가지를 모두 넣으면 클라이언트 요청은 물론이고, 오류 페이지 요청에서도 필터가 호출된다.
→ 아무것도 넣지 않으면 기본 값이 DispatcherType.REQUEST 이기 때문에, 클라이언트의 요청이 있는 경우에만 필터가 적용된다.
→ 특별히 오류 페이지 경로도 필터를 적용할 것이 아니면, 기본 값을 그대로 사용하면 된다.
# 2. 서블릿 예외 처리 - 인터셉터
@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().split("-")[0];
request.setAttribute(LOG_ID, uuid);
log.info("REQUEST [{}][{}][{}][{}]", uuid, request.getDispatcherType(), requestURI, handler);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle [{}]", modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
String requestURI = request.getRequestURI();
String logId = (String)request.getAttribute(LOG_ID);
log.info("RESPONSE [{}][{}][{}]", logId, request.getDispatcherType(), requestURI);
if (ex != null) {
log.error("afterCompletion error!!", ex);
}
}
}
- 필터에서는 필터를 등록할 때 어떤 DispatcherType인 경우에 필터를 적용할 지 선택할 수 있었다.
- 그런데 인터셉터는 서블릿이 제공하는 기능이 아니라 스프링이 제공하는 기능이다.
- 따라서 DispatcherType과 무관하게 항상 호출된다.
- 대신 인터셉터는 아래와 같이 요청 경로에 따라 추가하거나 제외하기 쉽게 되어 있기 때문에, 아래 설정을 사용해서 오류 페이지 경로를 excludePathPatterns 를 사용해서 빼주면 된다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/css/**", "/*.ico", "/error", "/error-page/**")
}
}
# 전체 흐름 정리
/hello 정상 요청
WAS(/hello, dispatchType=REQUEST) -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러 -> View
/error-ex` 오류 요청
- 필터는 `DispatchType` 으로 중복 호출 제거 ( `dispatchType=REQUEST` )
- 인터셉터는 경로 정보로 중복 호출 제거( `excludePathPatterns("/error-page/**")` )
1. WAS(/error-ex, dispatchType=REQUEST) -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러
2. WAS(여기까지 전파) <- 필터 <- 서블릿 <- 인터셉터 <- 컨트롤러(예외발생)
3. WAS 오류 페이지 확인
4. WAS(/error-page/500, dispatchType=ERROR) -> 필터(x) -> 서블릿 -> 인터셉터(x) -> 컨트 롤러(/error-page/500) -> View
'Spring' 카테고리의 다른 글
[JPA] findById() 와 getReferenceById() (2) | 2024.02.09 |
---|---|
Spring Security + JWT 흐름 간략하게 (0) | 2024.01.21 |
서블릿 (0) | 2023.12.28 |
서블릿 필터, 인터셉터 (1) | 2023.12.24 |
쿠키와 세션, 그리고 서블릿 HTTP 세션 (1) | 2023.12.23 |