Filter를 등록하는 4가지 방법
7431
안녕하세요.
정리 강의를 들으면서 Filter를 스프링 빈으로 등록하는 방법을 따라하다 버전 차이인지, 스프링 부트의 설정 차이인지, 에러가 발생하더군요.
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가 이미 빈으로 등록되어서 중복 등록이 안된다고 써져있었습니다.
그래서 이에 대해 찾아본 결과를 공유하고자 글을 작성합니다.
아래 글은 제 블로그에도 정리되어 있습니다. (홍보...ㅎㅎ..)
@Configuration
LogFilter - 로그 필터
@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);
}
}
}LoginCheckFilter - 로그인 필터
@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);
}
}
}FilterConfig - Filter 등록
@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를 설정할 수 있습니다.
@Component
LogFilter
@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);
}
}
}LoginCheckFilter
@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애노테이션을 이용해 순서를 설정할 수 있습니다.기본 URL Pattern이
/*이며 설정할 수 없습니다.
@WebFilter + @ServletComponentScan
LogFilter
@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);
}
}
}
LoginCheckFilter
@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);
}
}
}
MainApplication
@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"})
@WebFilter + @Component
LogFilter
@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);
}
}
}
LoginCheckFilter
@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);
}
}
}
실행 결과
[/] LogFilter doFilter Start
[/] LoginFilter doFilter Start
[/] LoginFilter doFilter End
[/] LogFilter doFilter End
특징
두 번째 방법과 세 번째 방법을 모두 사용하는 방법입니다.
설정을 위한 별개의 파일이 필요하지 않습니다.
컴포넌트 스캔 방식을 사용하기 때문에
@ServletComponentScan도 필요없습니다.
@Order애노테이션을 이용해 순서를 설정할 수 있습니다.@WebFilter의value나urlPatterns파라미터를 이용해 베이스 URL이나 Whitelist 방식으로 설정할 수 있습니다.@WebFilter("/filter/*")@WebFilter({"/login", "/items"})@WebFilter(urlPatterns = "/filter/*")@WebFilter(urlPatterns = {"/login", "/items"})
애노테이션이 기본으로 3개가 필요합니다.
정리

결론
필터를 사용하기 위한 4가지 방식을 알아보았습니다.
첫 번째 방법(@Configuration + FilterRegistrationBean)과 두 번째, 세 번째 방법을 합친 네 번째 방법(@WebFilter + @Component) 중에서 고려하면됩니다.
저의 경우에는 @Configuration + FilterRegistrationBean을 더 맘에 드는데, 이유는 Filter Class 위에 애노테이션을 여러개 붙이는 것 보다, 별도의 생성 파일을 하나 만들어서 관리하는게 더 편할 것 같아서였습니다.
하지만, @WebFilter + @Component은 스프링 빈으로 등록하는 방법이기에, 다른 스프링 빈을 의존성 주입 받을 수 있습니다. 그런 경우에는 첫 번째 방법으론 할 수 없으니, 네 번째 방법을 사용하면 될 것 같습니다.
답변 0
MVC 패턴을 정확히 익힐려면 어떻게 해야할까요?
0
372
1
선생님 조언 부탁드립니다.
0
301
0
WebFlux를 실무에 적용하기 전에 고민이 있습니다.
0
322
0
커리큘럼 고민
0
378
1
스프링 백엔드 개발 로드맵
0
468
1
Spring 공부 어떤 강의 순서로 듣는게 좋은가요?
0
722
1
프로젝트와 강의 우선 순위 관련 질문드립니다!
1
477
1
코틀린 개발자로 취업하게 되면서 고민이 생겼습니다.
0
416
1
강의 구입에 관한 질문입니다(설연휴 할인 관련)
0
394
1
학습 방향에 고민이 있습니다.
0
510
1
관리자권한으로 실행 자체가 뜨지 않으면 어떻게 해야할까요?
0
405
1
스프링 선수학습이 필요한가요?
1
518
1





