꼬물꼬물
필터(Filter)와 인터셉터(Interceptor) 본문
Filter와 Interceptor
- 스프링에서 요청이 Controller Layer로 들어오기 전 처리해야하는 작업
- 인증, 인가, XSS 방어, 데이터 압축, 인코딩
- 이러한 작업은 모든 컨트롤러 메서드에서 실행하는 것이 아닌 공통적으로 처리하는 것이 효율적이다.
- AOP(Aspect Oriented Programming): 관점 지향 프로그래밍
- 공통 관심사항과 핵심 관심사항으로 분리
- AOP(Aspect Oriented Programming): 관점 지향 프로그래밍
# Filter
- 서블릿 필터는 요청이 서블릿으로 전송되기 전에 요청을 가로채고 처리하는데 사용할 수 있다.
- 또한, 서블릿이 완료되고 컨테이너가 다시 클라이언트에게 응답시, 작업을 처리할 수 있다.
- 인증 필터
- 응답 데이터 압축
- 가장 앞단에 존재하는 포스트 컨트롤러인 디스패처 서블릿 요청 전,후에 부가적인 작업을 처리할 수 있는 기능을 제공한다.
- doFilter 메서드에서 필터링을 수행
✔️ 서블릿 필터 인터페이스(implements Filter)의 수명주기
public class Service implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
- init()
- 호출 시기: 컨테이너가 필터를 초기화할 때
- 필터 수명 주기에 한 번만 호출되며, 해당 메서드의 모든 리소스를 초기화해야 한다.
- FilterConfig는 컨테이너에서 초기화 매개변수와 서블릿 컨텍스트 개체를 제공한다.
- doFilter()
- 자원에 필터를 적용해야 할 때, 컨테이너가 매번 호출한다.
- 컨테이너는 필터에 대한 요청 및 으압 개체 함조를 제공한다.
- FilterChain은 다음 필터를 사용하는데 호출
- destroy()
- 컨테이너가 Filter 인스턴스를 삭제하기 전 메서드를 호출한다.
- 필터에 의해 열린 모든 리소스를 반환한다.
- 한 번만 호출된다.
1. FilterRegistrationBean 사용하기
Controller.java
@Slf4j
@RestController
@RequestMapping("/api")
public class controller {
@GetMapping("/test")
public String test(){
log.info("call test method");
return "test";
}
@GetMapping("/filter/test")
public String filterTest(){
log.info("call filterTest method");
return "filter Test";
}
}
Application.java
@SpringBootApplication
public class TodayApplication {
public static void main(String[] args) {
SpringApplication.run(TodayApplication.class, args);
}
@Bean
public FilterRegistrationBean setFilterRegistration(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
filterRegistrationBean.addUrlPatterns("/api/filter/*"); // /api/filter로 들어오는 경우 Myfilter 실행
return filterRegistrationBean;
}
}
MyFilter.java
@Slf4j
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("init MyFilter");
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("doFilter MyFilter, uri : {}", ((HttpServletRequest)request).getRequestURL());
chain.doFilter(request, response);
}
@Override
public void destroy() {
log.info("destroy MyFilter");
Filter.super.destroy();
}
}
- 어플리케이션 실행
- localhost:8080/api/filter/test
- filter가 실행되고 그 다음 controller의 메서드가 실행된다.
- 종료
2. @WebFilter + @ServletComponentScan 사용하기
- @ServletComponentScan 어노테이션을 @Configuration 어노테이션이 설정된 곳에 걸어주기
- 필터에 @WebFilter 어노테이션 사용
Application.java
@ServletComponentScan
@SpringBootApplication
public class TodayApplication {
public static void main(String[] args) {
SpringApplication.run(TodayApplication.class, args);
}
}
MyFilterAnnotation.java
@Slf4j
@WebFilter(urlPatterns = {"/api/filter/*"})
public class MyFilterAnnotation implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
log.info("init MyFilterAnnotation");
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("doFilter MyFilterAnnotation, uri : {}", ((HttpServletRequest)request).getRequestURL());
chain.doFilter(request, response);
}
@Override
public void destroy() {
log.info("destroy MyFilterAnnotation");
Filter.super.destroy();
}
}
- 어플리케이션 실행
- localhost:8080/api/filter/test
- 종료
[참고]
# 인터셉터(Interceptor)
- 스프링이 제공하는 기술로 디스패처 서블릿이 컨트롤러를 호출하기 전과 후에 요청을 가로채 응답을 참조하거나 가공할 수 있게 도와준다.
- 인터셉터는 필터와 다르게 스프링 컨텍스트 내부에서 동작한다.
- 디스패처 서블릿(Dispatcher Servlet)은 내부적으로 핸들러 매핑을 통해 적절한 컨트롤러를 찾도록 요청한다.
- 그 결과로 실행 체인(HandlerExecutionChain)을 반환한다.
- 실행 체인은 스프링 컨테이너에 인터셉터가 등록되어 있다면 인터셉터들을 순차적으로 거친 후 컨트롤러를 실행하도록 한다.
인터셉터의 실행주기
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
- preHandle()
- 컨트롤러가 호출되기 전에 실행된다.
- 요청 데이터 전처리, 가공 등에 사용
- postHandle()
- 컨트롤러가 호출된 후에 실행된다.
- 후처리 작업이 있을 때 사용
- afterCompletion()
- 뷰 생성을 포함한 모든 작업이 완료 된 후에 실행된다.
[정리]
- 필터는 Java가 지원, 인터셉터는 Spring이 지원하는 기능이다.
- 필터는 Dispatcher Servlet보다 앞에서 동작
- 인터셉터는 필터랑 달리 컨트롤러가 동작한 후에 작업을 처리한다.
[참고]
'코딩 > CS' 카테고리의 다른 글
기초 정렬 알고리즘 (0) | 2022.11.07 |
---|---|
페이지 교체 알고리즘 (0) | 2022.11.01 |
CPU 작동 원리 (0) | 2022.09.20 |
JDBC, SQL Mapper, ORM (0) | 2022.09.05 |
Day2 질문 (0) | 2022.04.25 |