참고글



필터 객체의 처리 조건
필터는 클라이언트가 서버의 특정 자원을 요청할 때 해당 요청을 필터링 처리하는것이 목적입니다. 그러나 여기서 말하는 클라이언트는 브라우저만 해당되는것은 아닙니다. 즉 브라우저가 서블릿이나 JSP를 요청할수도 있지만 RequestDispatcher 객체의 include()forward() 를 통해 JSP에서 JSP로 서블릿에서 서블릿으로 요청을 하는경우도 있습니다. 

또한 웹 컴포넌트에서 요청을 처리하다 예외가 발생하고 예외를 처리하지 못해 웹 컨테이너로 던져진 경우 설정에 따라 웹 컨테이너가 특정 에러 처리 페이지에 처리를 요청하기도 합니다.

즉 서버의 자원을 요청하는 케이스는 다음과 같습니다.
  • 브라우저같은 HTTP 클라이언트로부터 요청이 오는 경우 (REQUEST)
  • RequestDispatcher#include()를 통한 요청 (INCLUDE)
  • RequestDispatcher#forward()를 통한 요청 (FORWARD)
  • 웹 컴포넌트에서 예외가 발생하여 서블릿 컨테이너에서 에러처리 페이지로 요청한 경우 (ERROR)



web.xml에 dispatcher 설정하기
<dispatcher> 태그를 사용하면 필터가 적용되는 dispatcher의 타입을 지정할 수 있습니다. 따로 설정을 하지 않은 경우의 기본값은 REQUEST인데 만약 직접 FORWARDERROR등으로 설정을 해준다면 REQUEST를 추가적으로 다시 지정해 주어야 브라우저의 요청이 필터링됩니다.
      <filter-mapping>
            <filter-name>loggingFilter</filter-name>
            <url-pattern>/*</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>INCLUDE</dispatcher>
            <dispatcher>FORWARD</dispatcher>
            <dispatcher>ERROR</dispatcher>
            <dispatcher>ASYNC</dispatcher>
      </filter-mapping>
cs

REQUEST : 클라이언트의 요청인 경우 필터를 적용한다.
FORWARD : forward() 를 통해서 제어 흐름이 이동한 경우에 필터를 적용한다.
INCLUDE : include()를 통해서 포함되는 경우에 필터를 적용한다.
ERROR : 예외발생시 예외 처리 페이지를 요청하는 경우 필터를 적용한다.
ASYNC : (어떤 경우에 사용하는지 아직 모르지만 추후 따로 포스팅 할 예정)



테스트 예제
dispatcher 설정으로 ERROR를 지정하고 서버가 예외 처리 페이지를 요청할 때 필터가 적용되는지 테스트 해보도록 하겠습니다.

SimpleFilter.java - dispatcher 설정시 사용할 필터로 "심플필터" 라는 문자열을 콘솔 출력 하는 필터
dest.jsp - 브라우저에서 호출할 jsp 페이지로 호출하면 NullPointerException이 발생하도록 되어있음
internalEx.jsp - 웹어플리케이션의 특정 페이지에서 예외가 발생하면 서버에서 호출할 페이지
web.xml - 에러 처리 페이지 설정 및 필터 설정 등록


SimpleFilter.java
단순히 "심플필터 통과" 라는 문자열을 표준 출력하는 필터입니다.
package test;
 
 
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
 
 
public class SimpleFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {}
    
    public void doFilter(ServletRequest request, ServletResponse  response, FilterChain chain)
            throws IOException, ServletException {
        
        System.out.println("심플필터 통과!");
        chain.doFilter(request, response);
        
    }
 
 
    public void destroy() {}
}
 
cs


dest.jsp
브라우저에서 테스트시 호출할 페이지입니다. NullPointerException이 발생하도록 되어있기 때문에 서버에 의해 internalEx.jsp로 제어가 이동합니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"   pageEncoding="UTF-8"%>
      
<!DOCTYPE html>
<html>
<head>
      <meta charset="UTF-8">
</head>
<body>
      <%
            String nullStr = null;
            System.out.println(nullStr.toString());  //NullPointerException 발생 시점
      %>
</body>
</html>
 
cs


internalEx.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"   pageEncoding="UTF-8"%>
 
 
<html>
<head>
</head>
<body>
      <%
            System.out.println("예외가 발생하였음!");
      %>
      
      <h1>예외 처리 페이지입니다.</h1>
</body>
</html>
 
cs



web.xml
핵심은 SimpleFilter 설정에 걸어둔 dispatcher 설정이며, ERROR로 지정했기 때문에 오류로 인해 internalEx.jsp를 요청한것이 아니라면(브라우저로부터의 요청 등) SimpleFilter를 통과하지 않습니다.
      <error-page>
            <exception-type>java.lang.NullPointerException</exception-type>
            <location>/internalEx.jsp</location>
      </error-page>
      
      
      <filter>
            <filter-name>simpleFilter</filter-name>
            <filter-class>test.SimpleFilter</filter-class>
      </filter>
      
      <filter-mapping>
            <filter-name>simpleFilter</filter-name>
            <url-pattern>/internalEx.jsp</url-pattern>
            <dispatcher>ERROR</dispatcher>
      </filter-mapping>
cs



테스트
브라우저에서 직접 /internalEx.jsp 를 호출했을때와 dest.jsp를 호출하여 오류가 발생하여 서버가 internalEx.jsp를 호출했을때 필터가 동작하는지를 볼것입니다.

브라우저로 dest.jsp를 호출하면 예외가 발생한 이후 콘솔로그에는 다음과 같이 출력됩니다.





이번에는 internalEx.jsp 를 직접 호출합니다. 앞의 두개의 출력문은 앞서 dest.jsp를 호출했을때의 출력이며 이번에는 예외가 발생하였음! 하나만 출력되었음을 알 수 있습니다.





dispatcher 설정이 필요한 이유
만약 보안 정책과 관련되어 a.jsp에 접근시에는 무조건 로그인이 되어있는지 확인이 필요하다고 가정합니다. 브라우저로부터의 요청은 필터 설정의 기본값인 REQUEST에 해당하므로 따로 디스패쳐 설정을 하지 않아도 로그인 확인 필터가 이 요청을 체크할것입니다. 그러나 a.jsp페이지와 관련없는 웹 컴포넌트에서 forward()include()를 통해 a.jsp에 접근하려 한다면 (즉 서버 내부로부터 접근 하는 경우) 이 요청을 필터링 할 수 없습니다. 따라서 이럴때에 dispatcher 설정을 추가로 등록하는것입니다.






관련글

블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

,