필터를 사용하면 JSP/서블릿 등을 실행하기 이전에 요청이 올바른지 혹은 자원에 접근할 수 있는 권한을 가졌는지의 여부를 미리 처리할 수 있습니다.
또한 JSP/서블릿이 생성한 응답 데이터를 변경하거나 취소할 수 있는 기능 또한 구현이 가능합니다.
필터란?
필터를 간단히 이야기하면 HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 클래스입니다.
필터는 클라이언트와 자원(jsp, servlet)의 사이에 위치하고 있으며 request정보를 알맞게 변경할 수 있으며
response(최종 자원의 요청 결과)를 알맞게 변경할 수 있습니다.
클라이언트와 자원 사이에 여러 개의 필터가 존재할 수 있으며 여러 개 생성된 필터들을 필터 체인(chain)을 형성하게 됩니다.
필터는 정보를 변경할 뿐만 아니라 흐름도 변경할 수 있습니다.
클라이언트의 요청을 필터 체인의 다음 단계에 보내는 것이 아니라 다른 자원의 결과를 클라리언트에 전송할 수도 있습니다.
이러한 기능은 사용자의 인증이나 권한 검사와 같은 기능을 구현할 때 사용할 수 있습니다.
필터의 구현
필터를 구현하는 데 있어 3개의 핵심 타입이 존재합니다.
javax.sevlet.Filter Interface : 클라이언트와 최종 자원 사이에 위치하는 필터를 나타내는 객체가 구현해야 하는 인터페이스입니다.
javax.servlet.ServletRequestWrapper Class : 필터가 요청을 변경한 결과를 저장하는 래퍼입니다.
javax.servlet.ServletResponseWrapper Class :필터가 응답을 변경하기 위해 사용하는 래퍼입니다.
Filter 인터페이스
Filter 인터페이스는 다음과 같은 메서드를 가지고 있으며 필터 기능을 제공할 클래스는 메서드를 재정의해야 합니다.
public void init(FilterConfig filterConfig) throws ServletException
필터를 초기화할 때 호출됩니다.
public void doFilter(Servlet request, Servlet response, FilterChain chain) throw java.io.IOException, ServletException
필터 기능을 수행합니다. chain을 이용해서 체인의 다음 필터로 처리를 전달할 수 있습니다.
public void destroy()
필터가 웹 컨테이너에서 삭제될 때 호출됩니다.
전형적인 필터의 구현 방법
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class Filter implements javax.servlet.Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//필터 초기화 작업
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//request 파라미터를 이용해서 요청의 필터 작업수행
//체인의 다음 필터처리 chain.doFilter(request,response);
//response를 이용하여 응답의 필터링 작업 수행
}
@Override
public void destroy() {
//필터가 사용한 자원을 반납
}
}
doFilter() 메서드는 요청이 있을 때마다 매번 실행된다.
doFilter()의 3번째 파라미터는 FilterChain 객체를 전달받으며 chain.doFilter(request, response)로 다음 체인에게 변경된 요청과 응답을 전달해 줄 수 있다.
필터 설정하는 두 가지 방법.
1. web.xml 이용하는 방법
2.@WebFilter 애노테이션을 사용하는 방법
web.xml 이용하기
<filter>
<filter-name>필터이름</filter-name>
<filter-class>패키지명을 포함한 필터 인터페이스를 구현한 클래스</filter-class>
<init-param>
<param-name>paramName</param-name>
<param-value>value</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>필터이름</filter-name>
<url-pattern>*.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
filter 태그는 웹 애플리케이션에서 사용할 필터를 지정한다,
filter-mapping 태그는 클라이언트가 어떤 요청을 할 경우 어떤 필터를 사용할지를 결정합니다
init-param 태그는 필터를 초기화할 때 즉 init() 메서드를 호출할 경우 전달할 파라미터를 설정합니다.
url-pattern 태그는 특정 URL에 대해서만 필터링할 때 사용된다.
url-pattern 태그 대신 servlet-name 태그를 사용해 특정 서블릿에 대한 요청에 대해 필터를 적용할 수 있다.
* dispatcher는 mapping의 자식 태그이며 상황에 따라 전달하기 위한 방법이다.
REQUEST(기본값) : 클라이언트의 요청인 경우 필터를 적용
FORWARD : 제어 흐름을 이동하는 경우 필터를 적용
INCLUDE : 포함되는 경우 필터를 적용
또한 웹브라우저의 요청이 동시에 여러 개의 필터 매핑이 적용되는 경우 web.xml파일에 표시한 순서대로 필터를 적용합니다.
@WebFilter 애노테이션을 사용하는 방법
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@WebFilter(filterName = "필터이름", urlPatterns = {"/a/*"})
public class Filter implements javax.servlet.Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//필터 초기화 작업
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//request 파라미터를 이용해서 요청의 필터 작업수행
//체인의 다음 필터처리 chain.doFilter(request,response);
//response를 이용하여 응답의 필터링 작업 수행
}
@Override
public void destroy() {
//필터가 사용한 자원을 반납
}
}
@WebFilter 애노테이션의 주요 속성
urlPartters : 필터를 적용할 URL 패턴 목록을 지정한다.
servletNames : 필터를 적용할 서블릿 이름 목록을 지정한다.
filterName : 필터의 이름을 지정한다.
initParams : 초기화 파라미터 목록을 지정한다.
dispatcherTypes : 필터를 적용할 범위 지정 기본값 DispatchType.REQUEST 열거 타입 이용
요청 및 응답 래퍼 클래스는 클라이언트의 요청을 변경하고 클라이언트로 가는 응답을 변경할 수 있어야합니다.
그러기 위해서는 Servlet(Request/Response) Wrapper 클래스를 이용해야 합니다.
이 클래스를 이용하면 요청정보를 변경하여 최종 자원인 서블릿/JSP에 자원을 전달할 수 있으며
최종 자원으로부터 응답을 변경하여 새로운 응답 정보를 클라이언트에게 보냅니다.
서블릿의 요청/응답 래퍼를 만들려면 javax.servlet 패키지의 정의되어 있는 Servlet(Requset/Response) Wrapper 클래스를 상속받아서 구현해야 하지만 대부분의 필터는 Http 프로토콜에 대한 요청과 응답을 필터링하므로 HttpServlet(Requset/Response) Wrapper 클래스를 상속받아 구현하는 것이 좋습니다.
다음은 현재 제가 만들고 있는 웹페이지에서 login을 하지 않을 상태로 내 정보 user URI를 요청하면 로그인 페이지로 이동하도록 만들었습니다.
package webprj.food.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@WebFilter(
filterName = "loginFilter",
urlPatterns = {"/html/user"}
)
public class Filter implements javax.servlet.Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpSession session =httpRequest.getSession();
boolean login = false;
if(session != null) {
if(session.getAttribute("User") != null) {
login =true;
}
}
if(login) {
chain.doFilter(request, response);
}else {
request.getRequestDispatcher("/html/login.jsp").forward(request, response);
}
}
@Override
public void destroy() {
}
}
필터를 사용하는 방법에는 여러 가지 종류가 있습니다.
보통은 다음과 같은 필터를 적용하는데
사용자 인증
캐싱 필터
자원 접근에 대한 로깅
응답 데이터 변환 HTML 변환 , 응답 헤더 변환, 데이터 암호화 등)
공통 기능 실행
등의 활용 방법이 존재합니다.
'SSR > Servlet & JSP' 카테고리의 다른 글
서블릿 예외 페이지 (0) | 2022.01.13 |
---|---|
서블릿 3.0 파일 업로드 (0) | 2020.05.30 |
DBCP를 이용해서 커넥션 풀 사용하기 (0) | 2020.05.20 |
JSP SCOPE (0) | 2020.05.13 |
HttpServletRequest/Response (0) | 2020.05.09 |
댓글