저번에 Filter 와 HandlerInterceptor의 차이점에 대해서 공부를 해보았다.
https://tech-monster.tistory.com/119
이번에는 이것들을 직접 구현해서 적용해볼 것이다.
1. Filter 적용해보기
filter를 먼저 적용해보려고 한다.
들어오는 모든 요청과 응답을 로그로 남겨볼 것이다.
controller, LogFilter, WebConfig를 만들어서 작성하였다.
LogFilter.java
package filterinterceptorstudy.demo;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;
@Slf4j
public class LogFilter implements Filter {
@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) {
log.info("EXCEPTION {}", e.getMessage());
throw e;
} finally {
log.info("RESPONSE [{}][{}][{}]", uuid, request.getDispatcherType(), requestURI);
}
}
}
Filter의 doFilter를 override하면 불편한 점이 파라미터가 ServletRequest, ServletResponse로 들어온다는 점이다.
HttpServletRequest와 HttpServletResponse로 다운 캐스팅을 해줘야 사용하기가 편안하다.
WebConfig.java
package filterinterceptorstudy.demo;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
return filterRegistrationBean;
}
}
FilterRegistrationBean을 이용해서 Filter를 등록한다.
딱 보면 뭐... filter를 등록하고, 현재 등록중인 filter의 실행 순서, 적용될 url pattern, dispatcher 타입을 설정하는 것으로
딱~ 읽어보면 어떤 기능인지 그냥 보인다. 보여...
Controller.java
package filterinterceptorstudy.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
@GetMapping("/test-logFilter")
public String testLogFilter(String test){
return "ok!";
}
}
이렇게 서버를 켜보고 한 번 실행을 해보려 한다. 과연...
왜 두번이냐 할텐데 두번 실행했다.
이렇게 filter가 적용된 것을 확인할 수 있다.
2. HandlerInterceptor 적용해보기
LogInterceptor.java
package filterinterceptorstudy.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
@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);
log.info("REQUEST - HandlerInterceptor [{}][{}][{}][{}]", 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 - HandlerInterceptor [{}][{}][{}]", logId, request.getDispatcherType(), requestURI);
if (ex != null) {
log.error("afterCompletion error!!", ex);
}
}
}
WebConfig.java 수정
package filterinterceptorstudy.demo;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
@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/**");//오류 페이지 경로
}
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);
return filterRegistrationBean;
}
}
실행 결과
filter가 먼저 실행이 되고 Interceptor가 실행되는 것을 확인할 수 있다.
이렇게 적용을 해봤는데... 정리해보니 크게 어려운건 없었다.
'Spring > 스프링 기본' 카테고리의 다른 글
오류 처리 / Bean Validation (0) | 2022.03.18 |
---|---|
오류 처리 / validation & bindingResult (0) | 2022.03.18 |
Filters vs HandlerInterceptors - 개념 (0) | 2022.02.28 |
Glory of Rest 란 뭘까? + HATEOS 적용기 (0) | 2022.02.16 |
Spring Web Socket 적용하기 (2) | 2022.02.04 |