필터 - 서블릿이 제공하는 기능
인터셉터 - 스프링이 제공하는 기능
웹과 관련된 공통 관심사항을 처리함
적용되는 순서와 범위, 사용방법이 다름
인터셉터가 더 편리하고 다양한 기능을 제공함
필터
필터 제한
HTTP 요청 -> WAS -> 필터 -> 디스패쳐 서블릿 -> 컨트롤러 //로그인 사용자
HTTP 요청 -> WAS -> 필터(적절하지 않은 요청이라 판단, 서블릿 호출X) //비 로그인 사용자
필터 체인
HTTP 요청 -> WAS -> 필터1 -> 필터2 -> 필터3 -> 서블릿 -> 컨트롤러
필터는 체인으로 구성되는데, 중간에 필터를 자유롭게 추가할 수 있다. 예를 들어서 로그를 남기는 필터를 먼저 적용하
고, 그 다음에 로그인 여부를 체크하는 필터를 만들 수 있다.
필터 인터페이스를 구현하고 등록하면 서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고, 관리한다.
- init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
- doFilter(): 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
- destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.
@Slf4j
public class MyFilter implements Filter {
@Override // Filter 인터페이스를 보면 default로 되어 있어서 구현하진 않아도 됨
public void init(FinterConfig filterConfig) throws ServletException {
log.info("필터 초기화");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException {
// ServletRequest request는 HTTP 요청이 아닌 것까지 고려해서 만든 인터페이스
// HTTP를 사용하려면 HttpServletRequest로 다운케스팅
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
chain.doFilter(request, response); // 다음 필터 호출. 없으면 서블릿 호출.
}
@Override // Filter 인터페이스를 보면 default로 되어 있어서 구현하진 않아도 됨
public void destroy() {
log.info("필터 종료");
}
}
필터를 쓸 수 있게 등록해줘야 함
@Configuration
public class WebConfig {
@Bean // 스프링 빈으로 등록해줘야 함. 스프링부트가 WAS를 실행할때 필터를 같이 넣어서 실행함
public FilterRegistrationBean myFilter() {
new FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new MyFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/*"); // 모든 요청에 대해서 필터 동작
return filterRegistrationBean;
}
}
인터셉터
스프링 인터셉터 흐름
HTTP 요청 -> WAS -> 필터 -> 디스패쳐 서블릿 -> 인터셉터1 -> 인터셉터2 -> 컨트롤러
HandlerInterceptor 인터페이스 구현하면 됨
preHandle : 컨트롤러 호출 전 (무조건 호출)
postHandle : 컨트롤러 호출 후 (에러나면 미호출)
afterCompletion : http 요청 완료 후(viewResolver 호출, view 랜더링 후) (무조건 호출)
인터셉터는 스프링 MVC 구조에 특화된 필터 기능을 제공한다고 이해하면 된다. 스프링 MVC를 사용하고, 특별히 필터를 꼭 사용해야 하는 상황이 아니라면 인터셉터를 사용하는 것이 더 편리하다.
@Slf4j
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 인터셉터는 HttpServletRequest를 바로 쓸 수 있음
String requestURI = request.getRequestURI();
return true; // false면 컨트롤러 호출도 안되고 종료
}
@Override
public void postHandler(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
// modelAndView 확인 가능
log.info("postHandler [{}]", modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 에러 발생시 확인 가능
if (ex != null) log.error("afterCompletion error!", ex)
}
}
필터와 마찬가지로 등록해줘야 함
아까 config 파일에 추가
@Configuration // 추가
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.order(1)
.addPathPatterns("/**") // 모든 요청에 대해 인터셉터 동작
.excludePathPatterns("/css/**", "/*.ico", "/error"); // 그 중에 해당 경로는 인터셉터 동작하지마
}
.
.
.
}
'SpringBoot' 카테고리의 다른 글
swagger ui 에서 json 이쁘게 출력하기 (springfox 2.9.2 -> 3.0.0) (0) | 2024.10.30 |
---|---|
@Transactional 롤백 (0) | 2024.07.22 |
쿠키, 세션 구현, 동작 원리 (0) | 2024.05.17 |
bindingResult 가 쌓이는 과정, @Valid (0) | 2024.05.16 |
Spring MVC 구조와 동작 원리 (0) | 2024.05.09 |
댓글