필터와 인터셉터는 웹과 관련된 공통 관심사 (로그인, 사용자 권한)
를 처리할 때 주로 사용된다.
물론 공통 관심사는 AOP로도 해결할 수 있지만, 웹과 관련된 공통 관심사를 처리할 때에는 HTTP header나 URL 정보 등이 필요한데, 필터
와 인터셉터
의 경우 HttpServletRequest를 제공하기 때문이다.
HTTP 요청 -> WAS -> 필터1 -> 필터2 -> 필터3 -> Dispatcher Servlet -> 컨트롤러
이때, 필터에서 적절하지 않은 요청이라고 판단하면 dispatcherServlet을 호출하지 않고 요청을 끝낼 수도 있다.
ex) 로그인 정보가 일치하지 않을 경우
ServletRequest
와 ServletResponse
를 제공하는 것을 확인할 수 있으며, HttpServletRequest , HttpServletResponse
로 다운캐스팅하여 사용할 수 있다.
필터 인터페이스를 구현하고 등록하면 서블릿 컨테이너가 필터를 싱글톤 객체로 생성하고 관리한다.
필터는 다음의 3가지 메서드로 구성된다.
init()
: 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출된다.
doFilter()
: 고객의 요청이 올 때 마다 해당 메서드가 호출된다. 필터의 로직을 구현하면 된다.
doFilter() 메서드는 파라미터에 filterchain을 가지고 있는데, filterchain.doFilter(request, response);
메서드를 호출하게 되면,
다음 필터가 있으면 필터를 호출하고, 필터가 없으면 dispatcherServlet을 호출한다.
만약 이 로직을 호출하지 않으면 다음 단계로 진행되지 않기 때문에, 특별한 경우를 제외하고 반드시 호출해야한다.
destroy()
: 필터 종료 메서드, 서블릿 컨테이너가 종료될 때 호출된다.
필터 등록 방법에는 여러가지가 있지만, 스프링에서 제공하는
FilterRegistrationBean
을 사용해서 등록하면 된다.
setFilter()
: 등록할 필터를 지정한다.setOrder()
: 필터 체인 내에서 해당 필터의 순서를 지정한다.addUrlPatterns()
: 필터를 적용할 URL 패턴을 지정하며, 한번에 여러 패턴을 지정할 수 있다.String[] whitelist
: 요청을 허용할 URI 경로를 지정한다.
doFilter() 메서드 내에서 요청 URI가 whitelist에 포함될 경우 바로 다음 필터를 호출하도록 했다.
isLoginCheckPath()
: 해당 요청이 whitelist에 있을 경우 바로 다음 필터를 호출하며, 그렇지 않을 경우 사용자를 확인하는 로직을 수행한다.
해당 메서드 내에서는 세션이 존재하는지 확인 후, 존재하지 않으면 로그인 화면으로 redirect 한다.
sendRedirect("/login?redirectURL=" + requestURI)
: 이때, 로그인 후 사용자가 기존에 요청했던 화면으로 바로 이동시키기 위해 파라미터로 기존 요청 URI를 넘긴다.