📕🐘 도로락 - 코끼리를 냉장고에 넣는 방법
Servlet&Jsp | 2019. 1. 16. 11:23

[서블릿/JSP] web.xml에서 filter-mapping 설정의 dispatcher 설정에 대하여

참고글

필터 객체의 처리 조건

필터는 클라이언트가 서버의 특정 자원을 요청할 때 해당 요청을 필터링 처리하는 것이 목적입니다. 그러나 여기서 말하는 클라이언트는 브라우저만 해당되는 것은 아닙니다. 즉 브라우저가 서블릿이나 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>

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() {}
}

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>

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>

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>

테스트

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

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

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

dispatcher 설정이 필요한 이유

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

관련글

도로락

도로락

Writer

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