본문 바로가기

언어/jsp & javascript

[JSP&Javascript] FilterChain 이란?


Filter는 요청(Request)과 응답(Response)에 대한 정보들을 변경할 수 있게 개발자들에게 제공하는 서블린 컨테이너 입니다.



FilterChain은 이런 Filter가 여러개 모여서 하나의 체인을 형성하는 것 인데요,

체인을 형성한 Filter들을 거쳐가는 순서가 있습니다.

Filter가 요청정보, 즉 클라이언트가 요청하는 정보를 변경할 수 있는 서블린 컨테이너라고 위에서 언급 했는데, 

두번째 Filter는 이 클라이언트의 요청하는 정보가 아닌 첫번째 Filter에 의해서 변경된 요청 정보를 변경하게 됩니다.


그럼 먼저 Filter 인터페이스를 확인해 보겠습니다.

https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/Filter.html


destory() - 필터가 웹 컨테이너에서 삭제될 때 호출됩니다.

doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - 이 메서드를 통해서 요청(Request)와 응답(Response)

쌍이 체인을 통과할 때마다 컨테이너에서 호출됩니다. 체인을 따라서 계속 다음에 존재하는 필터로 이동하는 것 입니다.

init() - 필터를 웹 컨테이너 내에 생성한 후 초기화할때 호출됩니다.


Filter를 상세히 보기 전에 이 Filter를 사용하기 위한 설정을 먼저 보겠습니다.

필터를 사용하기 위해서는 어떤 필터가 어떤 자원에 적용된다는 것을 서블릿/JSP 콘테이너에 알려주어야 합니다.

때문에 웹 어플리케이션 디렉토리의 /WEB-INF 디렉토리에 존재하는 web.xml을 통해서 이를 설정해 주어야 합니다.


1
2
3
4
5
6
7
8
9
10
11
<web-app>
    <filter>
        <filter-name>SessionShareFilter</filter-name>
        <filter-class>com.project1.test1.filters.HttpsFilter</filter-class>
    </filter>
 
    <filter-mapping>
        <filter-name>SessionShareFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
cs


위 web.xml을 보시면 HttpsFilter 부분은 Filter를 imiplements 한 제가 정의한 클래스입니다.

이를 SessionShareFilter라는 이름으로 별칭을 주었고, url을 모든 경로에 매핑시켰습니다.

어떤 클라이언트의 요청이 있으면 그 요청이 있는 어느url 주소든지간에 항상 호출되되게 매핑시켰습니다.


아래는 위 코드에서 설정한 HttpsFilter 클래스에 대한 내용입니다. ( Filter를 implements )


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class HttpsFilter implements Filter
{
 
    /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    @Override
    public void destroy()
    {
        // default
    }
 
    /* (non-Javadoc)
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        //1. request 파라미터를 이용해 요청의 필터 작업 수행
        //2. 체인의 다음 필터 처리
        chain.doFilter(httpsRequest, response);    // 3. response를 이용해 응답의 필터링 작업 
    }
 
    /* (non-Javadoc)
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    @Override
    public void init(FilterConfig arg0) throws ServletException
    {
        // default
    }
 
}
cs



위 코드에서 doFilter() 메소드에서 FilterChain 객체를 세번째 파라미터로 전달받게 되는데, 이는 클라이언트가 요청한 자원이 거쳐가게 되는 필터체인을 나타냅니다. chain.doFilter 메서드를 통해 계속적으로 doFilter를 호출하는것을 보실 수 있죠.

근데, 1,2,3 이라는 순서를 통해서 요청을 필터링한 필터객체가 또다시 응답을 필터링한다는것을 확인 할 수 있습니다.


1. request 파라미터를 이용해서 클라이언트의 요청을 필터링합니다.

   RequestWrapper 라는 클래스를 사용해 클라이언트의 변경을 요청하게 됩니다.

2. 1번에서 생성한 RequestWrapper 클래스에 response를 설정해줍니다.

3. chain.doFilter를 이용해서 응답을 필터링합니다.



Wrapper Class

위에서 언급한 RequestWrapper 에 대해서 설명드리겠습니다.

필터가 필터로서의 제 기능을 위해서는 클라이언트의 Request를 변경하고, 또한 클라이언트로 되돌아가는 Response를 변경 할 수 있어야 합니다. 이러한 기능을 도와주는것이 HttpServletRequestWrapper 클래스와 HttpServletResponseWrapper 클래스입니다.

이 클래스들을 상속받아 구현시켜서 보통 많이 사용하게 됩니다.


필터를 통해서 변경하고 싶은 정보가 있을 경우, 그 정보를 추출하는 메소드를 알맞게 오버라이딩 한 후 필터의 doFilter() 메서드로 넘겨주기만 하면 됩니다.


예를들어서 다음 코드에서 HttpServletReqeustWrapper를 상속받은 HttpsReqeustWrapper 라는 클래스가 있습니다.

1
2
3
4
5
6
7
8
public class HttpsRequestWrapper extends HttpServletRequestWrapper
{
    private HttpServletResponse response = null;
 
    public void setResponse(final HttpServletResponse response)    {
        this.response = response;
    }
}
cs


이를 통해서 response를 HttpServletResponse 객체에 저장해주고, 위에서 설명드린 doFilter() 에서 httpRequestWrapper를 넘겨줌으로써 체인을 연결시킬 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class HttpsFilter implements Filter
{
 
    /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    @Override
    public void destroy()
    {
        // default
    }
 
    /* (non-Javadoc)
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        HttpsRequestWrapper httpsRequest = new HttpsRequestWrapper((HttpServletRequest)request);
        httpsRequest.setResponse((HttpServletResponse)response);
        chain.doFilter(httpsRequest, response);
    }
 
    /* (non-Javadoc)
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    @Override
    public void init(FilterConfig arg0) throws ServletException
    {
        // default
    }
 
}
 
cs



제가 이 FilterChain을 찾게 된 이유는 홈페이지 접속 시 header를 통해 JSESSION ID를 넘겨주게 되는데 이 값을 설정해주는 부분이 어디 있나 깊숙히 찾다가 FilterChain 까지 공부하게 되었습니다...




Today :
Yesterday :
Total :