본문 바로가기
SSR/Servlet & JSP

Filter

by oncerun 2020. 5. 24.
반응형

 

필터를 사용하면  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

댓글