Spring MVC/01.Spring @MVC

[Spring@MVC] 스프링과 Filter

  • -
반응형

처음 스프링을 공부하면서 Spring@MVC는 DispatcherServlet부터 관여하고 Filter는 Servlet 이전에 동작하기 때문에 Filter는 Spring과는 무관한 기술이라고 뇌리 속에 박고 있었는데..

스프링에서는 DelegatingFilterProxy라는 녀석이 Filter에서도 스프링과의 협업이 가능하게 한다. 참고로 이 클래스는 Spring Security에서 Filter를 사용하기 위해서 등장했다. 

이번 포스트에서는 Spring의 DelegatingFilterProxy에 대해서 살펴보자.

 

DelegatingFilterProxy

 

DelegatingFilterProxy

DelegatingFilterProxy는 스프링의 빈을 filter로 사용하기 위한 proxy filter로 spring 1.2에서 추가되었다.

 

javax.servlet.Filter는 servlet이 제공하는 기술로 Spring에서 직접 제어하기는 어려움이 있다. 그래서 스프링에서는 Proxy Filter를 만들어 기존의 Filter Chain에 투입시켰다. 이 필터는 사용자의 요청을 일단 받아서 실제 Filter역할을 하는 Spring Bean에게 연결하는 역할을 수행한다.

이를 통해서 Spring의 기술을 Filter 차원에서도 맘껏 사용할 수 있게 되었다. ㅎ

 

legacy 방식에서의 등록

legacy 방식에서는 아직 web.xml을 사용하기 때문에 여기에 filter를 등록한다. 그런데 여기서 주의할 점은 우리가 등록할 필터는 사용자 정의로 만든 필터가 아니라 DelegatingFilterProxy라는 점이다. 이 proxy filter가 요청을 받아서 Filter Bean에 넘겨준다는 점을 유의하자.

<filter>
    <filter-name>simpleFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
    
<filter-mapping>
    <filter-name>simpleFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

여기서 <filter-name> 도 중요한데 simpleFilter는 Filter로 동작할 빈의 이름이다.

또 한가지 주의할 점은 Filter Bean의 등록 시점이다. Filter는 DispatcherServlet 이전에 초기화가 되어야 하므로 Filter Bean의 등록도 그 이전에 되어야 함을 명심하자. 통상 Backend bean을 스캔, 등록하는 시점에 filter도 등록하도록 하자.

@Configuration
@ComponentScan({"com.quietjun.example.model"})
public class ApplicationConfig {
    @Bean
    public SimpleFilter simpleFilter() {
        return new SimpleFilter();
    }
}

 

springboot

SpringBoot는 자동 환경 설정이 생명이다. ㅎㅎ 그래서 boot로 넘어오면서는 굳이 DelegatingFilterProxy를 거치도록 프로그래밍하지 않아도 자동으로 처리된다.

단 필터를 컴포넌트로 등록할 때 @Component는 urlPattern을 지정할 수 없기 때문에 @WebFilter를 이용한다.

@WebFilter(urlPatterns = "/showMessage")
@Slf4j
public class SimpleFilter implements Filter{
    
    @Autowired
    HelloFilterService service;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("filter");
        HttpServletRequest hreq = (HttpServletRequest)request;
        hreq.setAttribute("fromFilter", service.sayHi("filter")+":" + System.currentTimeMillis());
        chain.doFilter(request, response);
    }
}

 

그리고 @WebFilter로 등록된 녀석을 스켄하고 빈으로 등록해주기 위해서 @ServletComponentScan을 이용한다. 이 애너테이션은 @WebFilter 뿐 아니라 @WebServlet, @WebListener 타입의 Servlet component를 스캔한다.

@SpringBootApplication
@ServletComponentScan(basePackageClasses = SimpleFilter.class)
public class MvcFilterApplication{

	public static void main(String[] args) {
		SpringApplication.run(MvcFilterApplication.class, args);
	}
}

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.