[Spring Boot] Filter 설정
Interceptor에 대한 설명은 해당 글을 참고
링크 : https://jangjjolkit.tistory.com/6
1. @Component or @ServletComponentScan WebFilter
임베디드 WAS의 경우, 자동 설정에 의해서 Filter를 구현할 클래스에 @Component만 붙여줘도 필터가 등록된다.
@Component
public class SomeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// ... before filter
chain.doFilter(request, response);
// ... after filter
}
}
characterEncodingFilter가 Ordered.HIGHEST_PRECEDENCE로 등록되기 때문에 해당값은 피해서 필터 순서를 지정해야 한다.
다른 필터도 마찬가지다.
chain.doFilter 이전에 작성한 코드들은 Request시에, 이후에 작성한 코드들은 Response시에 실행된다.
2개 이상 필터를 등록하는 경우 필터에 순서를 줘야한다면 @Order 또는 Ordered 인터페이스를 구현해야 한다.
@Component
@Order(1)
public class SomeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// ... before filter
chain.doFilter(request, response);
// ... after filter
}
}
그런데 @Component로 필터를 등록하면 url패턴을 지정할 수 없기 때문에 모든 url 패턴에 매핑된다.
@WebFilter 어노테이션을 이용하여 특정 url패턴에 매핑되는 필터를 추가할 수 있다.
@Component
@Order(1)
@WebFilter(urlPatterns="/some/*")
public class SomeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// ... before filter
chain.doFilter(request, response);
// ... after filter
}
}
이렇게 @Component로 스캔 후 필터로 등록 시 @WebFilter 어노테이션이 적용되지 않는다.
@ServletComponentScan 은 Spring Boot 내장 웹서버를 사용할 경우 서블릿 Component(@WebFilter, @WebServlet, @WebListener)를 스캔할 때 사용하는 어노테이션이다.
해당 어노테이션을 @SpringBootApplication이 붙어있는 메인클래스에 추가한다.
@ServletComponentScan
@SpringBootApplication
public class ApiApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
하지만 위 방식대로 진행할 경우 Filter가 두 번 실행되는 문제가 생길 수 있다. 이유는 이미 @Component로 Filter 클래스를 적용했는데 @ServletComponentScan 에서 @WebFilter 를 한번 더 스캔하기 때문이다.
때문에, @WebFilter 를 사용할 경우 @Component를 제거해주면 된다.
@Order(1)
@WebFilter(urlPatterns="/some/*")
public class SomeFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// ... before filter
chain.doFilter(request, response);
// ... after filter
}
}
필자는 api 암복호화 프로젝트를 진행할 때, 특정 url로 api 요청 시 필터 적용을 위해 해당 방법을 사용했다.
참고 : https://github.com/JangDaeHyeok/spring_api_server
2. FilterRegistrationBean
만약 조금 더 세밀한 제어나 Filter 클래스를 수정하지 못하는 경우 FilterRegistrationBean을 이용하여 필터를 등록할 수 있다. 위에서 정리한 방식과 다르게 config 클래스를 별도로 생성해야 하지만 @ServletComponentScan 어노테이션이나 필터 클래스에 적용한 어노테이션이 필요없다.
@Configuration
public class SomeFilterConfig {
@Bean
public void runSomeFilterRegistration() {
someFilterRegistration();
}
private FilterRegistrationBean<SomeFilter> someFilterRegistration() {
FilterRegistrationBean<SomeFilter> registration = new FilterRegistrationBean<Filter>();
registration.setFilter(new SomeFilter());
registration.addUrlPatterns("/some/*"); // url 패턴 설정
registration.addInitParameter("param1", "param_value1"); // 파라미터 설정
registration.setName("some-filter"); // 필터명 설정
registration.setOrder(1); // 순서 설정
return registration;
}
}
필자는 프로젝트 진행 중 어떠한 라이브러리 클래스를 별도로 제공했기 때문에, 필터로 적용 시 해당 방법을 사용했다.