이 글은 인프런의 김영한님의 스프링 MVC 2편을 보다가 "섹션 7. 로그인 처리 2 - 필터, 인터셉터"의 "정리" 부분에서 나오는 필터를 등록하는 다른 방법이 지금 내 환경(Spring boot 3.0)에서 먹히지 않아, 궁금해져서 찾은 내용을 담고 있다.
@Slf4j
public class LogFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LogFilter init()");
}
@Override
public void destroy() {
log.info("LogFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LogFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LogFilter doFilter End", requestURI);
}
}
}
@Slf4j
public class LoginCheckFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LoginCheckFilter init()");
}
@Override
public void destroy() {
log.info("LoginCheckFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LoginFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LoginFilter doFilter End", requestURI);
}
}
}
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<Filter> logFilter() {
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setFilter(new LogFilter());
bean.setOrder(1);
bean.addUrlPatterns("/*");
return bean;
}
@Bean
public FilterRegistrationBean<Filter> loginCheckFilter() {
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setFilter(new LoginCheckFilter());
bean.setOrder(2);
bean.addUrlPatterns("/*");
return bean;
}
}
[/] LogFilter doFilter Start
[/] LoginFilter doFilter Start
[/] LoginFilter doFilter End
[/] LogFilter doFilter End
@Configuration
이 붙은 객체)이 필요하다.setOrder()
를 통해 순서를 정할 수 있다.addUrlPatterns()
을 통해 베이스 URL 및 Whitelist를 설정할 수 있다.@Slf4j
@Component
@Order(1)
public class LogFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LogFilter init()");
}
@Override
public void destroy() {
log.info("LogFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LogFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LogFilter doFilter End", requestURI);
}
}
}
@Slf4j
@Component
@Order(2)
public class LoginCheckFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LoginCheckFilter init()");
}
@Override
public void destroy() {
log.info("LoginCheckFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LoginFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LoginFilter doFilter End", requestURI);
}
}
}
[/] LogFilter doFilter Start
[/] LoginFilter doFilter Start
[/] LoginFilter doFilter End
[/] LogFilter doFilter End
@Order
애노테이션을 이용해 순서를 설정할 수 있다./*
이며 설정할 수 없다.@Slf4j
@WebFilter
public class LogFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LogFilter init()");
}
@Override
public void destroy() {
log.info("LogFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LogFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LogFilter doFilter End", requestURI);
}
}
}
@Slf4j
@WebFilter
public class LoginCheckFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LoginCheckFilter init()");
}
@Override
public void destroy() {
log.info("LoginCheckFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LoginFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LoginFilter doFilter End", requestURI);
}
}
}
@ServletComponentScan
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCoreMvc26Application.class, args);
}
}
[/] LogFilter doFilter Start
[/] LoginFilter doFilter Start
[/] LoginFilter doFilter End
[/] LogFilter doFilter End
@ServletComponentScan
을 사용해야 한다.@Order
를 이용한 순서 등록을 사용할 수 없다.@WebFilter
의 value
나 urlPatterns
파라미터를 이용해 whitelist 방식으로 베이스 URL을 설정할 수 있다.@WebFilter("/filter/*")
@WebFilter({"/login", "/items"})
@WebFilter(urlPatterns = "/filter/*")
@WebFilter(urlPatterns = {"/login", "/items"})
@Slf4j
@WebFilter
@Component
@Order(1)
public class LogFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LogFilter init()");
}
@Override
public void destroy() {
log.info("LogFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LogFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LogFilter doFilter End", requestURI);
}
}
}
@Slf4j
@WebFilter
@Component
@Order(1)
public class LoginCheckFilter implements Filter {
@Override
public void init(
FilterConfig filterConfig
) throws ServletException {
log.info("LoginCheckFilter init()");
}
@Override
public void destroy() {
log.info("LoginCheckFilter destroy()");
}
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String requestURI = req.getRequestURI();
log.info("[{}] LoginFilter doFilter Start", requestURI);
try {
chain.doFilter(request, response);
} finally {
log.info("[{}] LoginFilter doFilter End", requestURI);
}
}
}
@ServletComponentScan
도 필요없다.@Order
애노테이션을 이용해 순서를 설정할 수 있다.@WebFilter
의 value
나 urlPatterns
파라미터를 이용해 베이스 URL이나 Whitelist 방식으로 설정할 수 있다.@WebFilter("/filter/*")
@WebFilter({"/login", "/items"})
@WebFilter(urlPatterns = "/filter/*")
@WebFilter(urlPatterns = {"/login", "/items"})
설정 방법 | 순서 설정 | 베이스 URL | Bean 여부 | |
---|---|---|---|---|
@Configuration | FilterRegistrationBean | setOrder | addUrlPatterns | X |
@Component | 없어도 됨 | @Order | 사용할 수 없음 | O |
@WebFilter | @ServletComponentScan | 사용할 수 없음 | value, urlPatterns 파라미터 | O |
@WebFilter + @Component | 없어도 됨 | @Order | value, urlPatterns 파라미터 | O |
첫 번째 방법과 네 번째 방법을 혼합하여 사용할 경우, 스프링 빈을 등록하는 과정에서 에러를 확인할 수 있다.
The bean 'logFilter', defined in class path resource [hello/springcoremvc26/config/FilterConfig.class], could not be registered.
A bean with that name has already been defined in file [/project/java/spring/spring-core-mvc2-6/out/production/classes/hello/springcoremvc26/web/filter/LogFilter.class] and overriding is disabled.
이유를 자세히 읽어보면, logFilter가 이미 빈으로 등록이 되었다고 되어있다고 되어 있다.
다른 글을 찾아보면 동일한 필터가 2번 호출된다고도 하던데, 아마 버전의 차이이거나 스프링 부트의 설정에서 빈을 중복으로 등록할 수 있도록 변경할 수 있는 것으로 보인다.
필터를 사용하기 위해서 4가지 방식을 알아보았다.
첫 번째 방법(@Configuration
+ FilterRegistrationBean
)과 두 번째, 세 번째 방법을 합친 네 번째 방법(@WebFilter
+ @Component
) 중에서 고려를 해야한다.
나의 경우에는 @Configuration
+ FilterRegistrationBean
을 더 선호하는데, 이유는 Filter Class 위에 애노테이션을 여러개 붙이는 것 보다, 별도의 생성 파일을 하나 만들어서 관리하는게 더 편할 것 같아서이다.
하지만, @WebFilter + @Component
은 스프링 빈으로 등록하는 방법이기에, 다른 스프링 빈을 의존성 주입 받을 수 있다. 그런 경우에는 첫 번째 방법으론 할 수 없으니, 네 번째 방법을 사용하자.
4 번째 방식에서 @WebFilter에 url패턴이 적용되지 않는거 같습니다.