티스토리 뷰

Servlet

필터

dev23 2024. 8. 13. 17:18
반응형

필터

- 필터란 브라우저에서 서블릿에 요청하거나 응답할 때 미리 요청이나 응답과 관련해 여러 가지 작업을 처리하는
기능이다.

- 한글 인코딩처럼 서블릿에서 반복적으로 처리해야 하는 작업이 있을 있는데, 이런 경우 서블릿의 공통 작업을 미리 필터에서 처리하면 반복해서 작업할 필요가 없을 것이다.

 

- 필터는 용도에 따라 크게 요청 필터와 응답 필터로 나뉘며 다음과 같은 API 있다.

 

 1. 요청 필터

  • 사용자 인증 및 권한 검사
  • 요청 시 요청 관련 로그 작업
  • 인코딩 기능

 2. 응답 필터

  • 응답 결과에 대한 암호화 작업
  • 서비스 시간 측정

3. 필터 관련 API

  • javax.servlet.Filter
  • javax.servlet.FilterChain
  • javax.servlet.FilterConfig

 

서블릿에서 제공하는 필터 관련 API 메서드

메서드 기능
destroy() 필터 소멸 컨테이너에 의해 호출되어 종료 작업을 수행한다.
doFilter() 요청/응답 컨테이너에 의해 호출되어 기능을 수행한다.
init() 필터 생성 컨테이너에 의해 호출되어 초기화 작업을 수행한다.

 

FilterConfig 메서드

메서드 기능
getFilterName() 필터 이름을 반환한다.
getInitParameter(String name) 매개변수 name 대한 값을 반환한다.
getServletContext() 서블릿 컨텍스트 객체를 반환한다.

 

사용자 정의 필터

- 사용자 정의 필터는 반드시 Filter 인터페이스를 구현해야하며, init(), doFilter(), destroy() 추상 메서드를 구현해
주어야 한다.

- 사용자 정의 필터를 생성하면 필터를 각각의 요청에 맞게 적용하기 위해 필터 매핑 해야 하는데, 필터를 매핑하는
방법은 다음 가지이다.

  • 애너테이션을 이용하는 방법
  • web.xml에 설정하는 방법

- 일반적으로 애너테이션을 이용하는 방법이 편리하므로 많이 사용한다.

 

Filter 이용한 한글 인코딩

- request.setCharacterEncoding("utf-8")과 같은 코드를 서블릿에 사용하지 않고 필터를 이용해 인코딩한다.

* login.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인</title>
</head>
<body>
	<form name="frmLogin" method="post" action="login" encType="UTF-8" >
		이름 : <input type="text" name="user_name" /><br>
		비밀번호 : <input type="password" name="user_pw" /><br>
		<input type="submit" value="로그인" />
		<input type="reset" value="다시 입력" />
	</form>
</body>
</html>

 

* LoginTest.java

package filter;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class LoginTest
 */
@WebServlet("/login")
public class LoginTest extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// request.setCharacterEncoding("utf-8"); post 방식으로 한글 전송 시 인코딩 작업을 생략한다.
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		String user_name = request.getParameter("user_name");
		String user_pw = request.getParameter("user_pw");
		
		out.print("<html><body>");
		out.print("이름은 " + user_name + "<br>");
		out.print("비밀번호는 " + user_pw + "<br>");
		out.print("</body></html>");
	}

}

 

- 코드 작성 후 톰캣을 재시작하고 브라우저에 localhost:[port]/[project_name]/login.html을 입력해 로그인 화면에
접속한다.

- 접속 후 한글 이름을 작성 후 [로그인] 버튼을 눌러 본다.

한글 이름 입력
한글 이름 입력 후 로그인 시 이름 문자가 정상적으로 출력되지 않음

 

- 한글 이름을 입력하고 로그인 버튼 클릭 시 입력한 한글 이름이 정상적으로 출력되지 않는 것을 확인했다.

- 이제 필터를 구현하여 이 문제를 해결한다.

 

* EncoderFilter.java

package filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

/**
 * Servlet Filter implementation class EncoderFilter
 */

// @WebFilter 애너테이션을 이용해 모든 요청이 필터를 거치게 한다.
@WebFilter("/*")
public class EncoderFilter implements Filter {
	// 사용자 정의 필터는 반드시 Filter 인터페이스를 구현해야 한다.

	ServletContext context;
	
    /**
     * Default constructor. 
     */
    public EncoderFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		System.out.println("destroy() 호출");
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	// doFilter 안에서 실제 필터 기능을 구현한다.
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("doFilter 호출");
		// 한글 인코딩 설정 작업을 한다.
		request.setCharacterEncoding("utf-8");
		// 웹 애플리케이션의 컨텍스트 이름을 가져온다.
		String context = ((HttpServletRequest)request).getContextPath();
		
		// 웹 브라우저에서 요청한 요청 URI 값을 가져온다.
		String pathInfo = ((HttpServletRequest)request).getRequestURI();
		
		// 요청 URI의 실제 값을 가져온다.
		String realPath = request.getRealPath(pathInfo);
		
		String msg = "Context 정보 : " + context +
				"\n URI 정보 : " + pathInfo +
				"\n 물리적 경로 : " + realPath;
		System.out.println(msg);
		// 다음 필터로 넘기는 작업을 수행한다.
		chain.doFilter(request, response);
	}

	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("utf-8 인코딩 ..............");
		context = fConfig.getServletContext();
	}


}

 

- 필터 작성 후 톰캣을 재시작하고 login.html에 접속하여 한글 이름을 입력하고 다시 로그인을 해 본다.

Filter 작성 후 정상적으로 출력되는 한글 이름

 

콘솔 출력 결과

 

- 다시 요청 시 정상적으로 한글 이름이 출력된다.

 

응답 필터

- 응답에 대해 수행하는 응답 필터다.

- 서블릿에서 요청과 응답에 대한 필터 기능은 동일한 필터가 수행한다.

- 필터에서 doFilter() 메서드를 기준으로 위쪽에 위치한 코드는 요청 필터 기능을 수행하고, 아래에 위치한 코드는 응답
필터 기능을 수행한다.

더보기

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

System.out.println("doFilter 호출");

// 한글 인코딩 설정 작업을 한다.

request.setCharacterEncoding("utf-8");

// 웹 애플리케이션의 컨텍스트 이름을 가져온다.

String context = ((HttpServletRequest)request).getContextPath();

 

// 웹 브라우저에서 요청한 요청 URI 값을 가져온다.

String pathInfo = ((HttpServletRequest)request).getRequestURI();

 

// 요청 URI의 실제 값을 가져온다.

String realPath = request.getRealPath(pathInfo);

 

String msg = "Context 정보 : " + context +

"\n URI 정보 : " + pathInfo +

"\n 물리적 경로 : " + realPath;

System.out.println(msg);

long begin = System.currentTimeMillis(); // 요청 필터에서 요청 처리 전의 시각을 구한다.

 

chain.doFilter(request, response);

// 응답 필터

long end = System.currentTimeMillis(); // 응답 필터에서 요청 처리 후의 시각을 구한다.

System.out.println("작업 시간 : " + (end - begin) + "ms"); // 작업 요청 전과 후의 시각 차를 구해 작업 수행 시간을 구한다.

}

 

작업 시간 구하기

- 응답 필터 기능을 이용해 로그인 요청 작업 수행 시간을 구한다.

 

* EncoderFilter.java

package filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

/**
 * Servlet Filter implementation class EncoderFilter
 */

// @WebFilter 애너테이션을 이용해 모든 요청이 필터를 거치게 한다.
@WebFilter("/*")
public class EncoderFilter implements Filter {
	// 사용자 정의 필터는 반드시 Filter 인터페이스를 구현해야 한다.

	ServletContext context;
	
    /**
     * Default constructor. 
     */
    public EncoderFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		System.out.println("destroy() 호출");
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	// doFilter 안에서 실제 필터 기능을 구현한다.
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		System.out.println("doFilter 호출");
		// 한글 인코딩 설정 작업을 한다.
		request.setCharacterEncoding("utf-8");
		// 웹 애플리케이션의 컨텍스트 이름을 가져온다.
		String context = ((HttpServletRequest)request).getContextPath();
		
		// 웹 브라우저에서 요청한 요청 URI 값을 가져온다.
		String pathInfo = ((HttpServletRequest)request).getRequestURI();
		
		// 요청 URI의 실제 값을 가져온다.
		String realPath = request.getRealPath(pathInfo);
		
		String msg = "Context 정보 : " + context +
				"\n URI 정보 : " + pathInfo +
				"\n 물리적 경로 : " + realPath;
		System.out.println(msg);
		
		long begin = System.currentTimeMillis(); // 요청 필터에서 요청 처리 전의 시각을 구한다.
		
		// 다음 필터로 넘기는 작업을 수행한다.  // 요청 필터
		chain.doFilter(request, response);
		
		// 응답 필터
		long end = System.currentTimeMillis(); // 응답 필터에서 요청 처리 후의 시각을 구한다.
		System.out.println("작업 시간 : " + (end - begin) + "ms"); // 작업 요청 전과 후의 시각 차를 구해 작업 수행 시간을 구한다.

	}

	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("utf-8 인코딩 ..............");
		context = fConfig.getServletContext();
	}


}

 

 

요청과 응답간 차

 

- 서블릿이나 JSP에서 공통으로 처리해야 작업을 필터에 구현해 놓고 사용하면 편리하다.

반응형

'Servlet' 카테고리의 다른 글

서블릿 Listener  (0) 2024.08.13
서블릿 URL 패턴  (0) 2024.08.13
서블릿 속성 및 스코프  (0) 2024.08.13
encodeURL()  (0) 2024.08.13
서블릿 - 세션 로그인 예제  (0) 2024.08.12
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
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
글 보관함