위로 아래

필터

필터(filter)

//filter.class 파일

package filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class ~Filter implements Filter {

	@Override
	public void init(FilterConfig fc) throws ServletException{
    
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
            
	}
    
	@Override
	public void destroy() {
    
	}
}
  1. HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 클래스
  2. 클라이언트와 서버 사이에서 request와 response 객체를 먼저 받아 사전, 사후 작업 등 공통적으로 필요한 부분을 처리하는 것
  3. 클라이언트의 요청이 웹 서버의 서블릿, JSP, HTML 페이지 같은 정적 리소스에 도달하기 전과, 정적 리소스에서 클라이언트로 응답하기 전에 필요한 전처리를 가능하게 함.
  4. 최종 자원과 클라이언트로 가는 응답(response) 사이에 위치하여, 최종 자원의 요청 결과를 알맞게 변경 가능.
  5. 클라이언트의 요청을 수행하지 않고, 다른 자원의 결과를 클라이언트에게 전송할 수도 있다 (사용자 인증이나 권한 검사 등에 사용)

 

필터 체인 (filter chain)

  1. 클라이언트와 정적 리소스 사이에 여러 개의 필터로 이루어진 필터 체인을 제공

 

 

사용 범위

  1. 사용자 인증
  2. 캐싱 필터
  3. 자원 접근에 대한 로깅
  4. 응답 데이터 변환 (HTML변환, 응답 헤더 변환, 데이터 암호화 등)
  5. 공통 기능 실행

 

 


web.xml 이용 Filter 구현

  1. ~filter.class 파일을 어떤 어떤 리소스에 적용할 건지 JSP 컨테이너에 알려주기 위해 web.xml에 적어놓는다.
  2. web.xml에 선언하면, 계속 만들 필요 없이 한 번만 만든 클래스를 재사용할 수 있다.
  3. <filter> 태그와 <filter-mapping>태그 사용
  4. web.xml 파일에 여러 개의 필터가 설정되어 있으면 선언된 순서대로 실행
// 기본형
<filter>
	<filter-name>Filter01</filter-name>
	<filter-class>filter.AuthenFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>Filter01</filter-name>
	<url-pattern>/jspEx/Filter01Process.jsp</url-pattern>
</filter-mapping>

 

태그 종류

  1. <filter> 태그 : 웹 어플리케이션에서 사용할 필터 지정
  2. <filter-name> 태그 : 필터의 이름 (filter와 filter-mapping에 들어가는 이름이 같아야 한다)
  3. <filter-mapping> 태그 : 특정 자원에 대해 어떤 필터를 사용할지 지정
  4. <filter-class> 태그 : 필터가 있는 위치
  5. <url-pattern>태그 : 클라이언트가 요청한 특정 URI에 대해서 필터링할 때 사용
  6. <init-param> 태그 : 필터를 초기화할 때(init()필터를 호출할 때) 전달할 파라미터를 설정
  7. <servlet-name>태그 : url-pattern 태그 대신에 사용할 수 있으며, 특정 서블릿에 대한 요청에 대해서 필터를 적용.
  8. <dispatcher>태그 : 필터가 적용되는 시점을 설정 가능 (filter-mapping 태그의 안 쪽에 위치)
    1. <dispatcher>REQUEST</dispatcher> : 클라이언트의 요청인 경우에 필터를 적용 (기본값)
    2. <dispatcher>FORWARD</dispatcher> : forwaed()를 통해서 제어 흐름을 이동하는 경우에 필터 적용
    3. <dispatcher>INCLUDE</dispatcher> : include()를 통해서 포함되는 경우에 필터 적용

 

다른 방법들

  1. @WebFilter 애노테이션 이용
  2. Filter 인터페이스 이용

 

 


Filter 인터페이스

Filter 인터페이스

  1. 클라이언트와 서버의 리소스 사이에 위치한 필터의 기능을 제공하기 위해 자바 클래스로 구현해야 함
  2. Filter 인터페이스 메소드 종류
    1. init () : 필터 인스턴스의 초기화 메소드
    2. doFilter () : 필터 기능을 작성하는 메소드
    3. destroy () : 필터 인스턴스의 종료 전에 호출되는 메소드

 

init() 메소드

@Override
public void init(FilterConfig fc) throws ServletException{}
  1. JSP 컨테이너 내에서 초기화 작업을 수행할 필터 인스턴스를 생성한 후 한 번만 호출
  2. JSP 컨테이너에 의해 호출되어 필터의 서비스가 시작되고 있음을 나타냄
  3. filterConfig
    1. init 메소드의 매개변수로 전달되는 객체.
    2. web.xml에서 <init-param> 태그를 통해 작성해준 정보들과, ServletContext에 대한 참조를 가지고 있다.
    3. getFilterName() : 필터 등록시 지정한 필터명 반환
    4. getInitParameter(String name) : web.xml에서 <init-param>의 <param-name>을 매개변수로 넣으면, <param-value>로 등록한 값이 반환. 없으면 null 리턴.
    5. getServletContext() : 필터가 속해있는 웹 어플리케이션의 ServletContext를 리턴
    6. getInitParameterNames() : 필터에 설정되어 있는 초기화 설정값들의 설정명을  Enumeration으로 리턴. (설정명들을 담은 목록 리턴)

 

doFilter() 메소드

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
	throws IOException, ServletException {}
  1. JSP 컨테이너가 필터를 리소스에 적용할 때마다 호출하는 메소드
  2. init() 메소드 후에 호출되며, 필터가 어떤 기능을 수행할 필요가 있을 때마다 호출
  3. 매개변수 ServletRequest 객체 : 체인을 따라 전달하는 요청
  4. 매개변수 ServletResponse 객체 : 체인을 따라 전달할 응답
  5. 매개변수 FilterChain 객체 : 체인에서 다음 필터를 호출하는데 사용
  6. 만약 호출 필터가 체인의 마지막 필터이면 체인의 끝에서 리소스를 호출

 

destroy() 메소드

  1. 필터 인스턴스를 종료하기 전에 호출하는 메소드
  2. 필터의 수명 동안 한 번만 호출
  3. JSP 컨테이너가 필터 인스턴스를 삭제하기 전에 청소 작업을 수행하는데 사용. (필터로 열린 리소스를 모두 닫을 수 있는 방법)
@Override
public void destroy() {}

 

 


예시

인코딩 필터

더보기
// web.xml 파일에 인코딩 필터 코드
<filter>
        <filter-name>Encoding Filter</filter-name>
        <filter-class>filter.CommonEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
</filter>
// CommonEncodingFilter.class 파일
package filter;

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 CommonEncodingFilter implements Filter {

    /**
     * 인코딩을 수행할 인코딩 캐릭터 셋 지정
     */
    private String encoding = null;

    /**
     * 필터 설정 관리자
     */
    protected FilterConfig filterConfig = null;
	
    /**
     * @return
     */
    public FilterConfig getFilterConfig() {
        return filterConfig;
    }

    /**
     * @param cfg
     */
    public void setFilterConfig(FilterConfig cfg) {
        filterConfig = cfg;
    }
	@Override
	public void destroy() {
		this.encoding = null;
	    this.filterConfig = null;
	}
	@Override
	public void doFilter(ServletRequest request, 
			   ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		  
		if (request.getCharacterEncoding() == null) {
	            if (encoding != null) {
	              request.setCharacterEncoding(encoding);
	            }
	        }
	        chain.doFilter(request, response);
	}
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	    this.filterConfig = filterConfig;
	    this.encoding = filterConfig.getInitParameter("encoding");
	}
}

 

null값 입력 오류 필터

더보기
//web.xml 파일에 null값 입력 오류 필터 코드

 <filter>
    	<filter-name>Filter01</filter-name>
    	<filter-class>filter.AuthenFilter</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>Filter01</filter-name>
    	<url-pattern>/jspEx/Filter01Process.jsp</url-pattern>
</filter-mapping>
// AutenFilter.class 파일
package filter;

import java.io.IOException;
import java.io.PrintWriter;
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 AuthenFilter implements Filter {

	@Override
	public void init(FilterConfig fc) throws ServletException{
		System.out.println("Filter01 초기화");
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("Filter01.jsp 수행...");
		String name = request.getParameter("name");
		
		if(name == null || name.equals("")) {
			response.setContentType("text/html; charset=UTF-8");
			PrintWriter writer = response.getWriter();
			String msg = "입력된 name값은 null입니다.";
			writer.println(msg);
			return;
		}
		chain.doFilter(request, response);
	}
	@Override
	public void destroy() {
		System.out.println("Filter01 해제");
	}
}
<!-- 테스트용 Filter01.jsp 파일 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="Filter01Process.jsp" method="post">
		<p>이름 : <input type="text" name="name"></p>
		<p><input type="submit" value="전송"></p>
	</form>
</body>
</html>
<!-- 처리페이지 Filter01Process.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		String name = request.getParameter("name");
	%>
	<p>입력된 name값 : <%=name %></p>
</body>
</html>

 

관리자 아이디 비밀번호 필터

더보기
// web.xml 파일에 관리자 아이디 비밀번호 필터 코드
<filter>
    	<filter-name>Filter02</filter-name>
    	<filter-class>filter.InitParamFilter</filter-class>
    	<init-param>
    		<param-name>param1</param-name>
    		<param-value>admin</param-value>
    	</init-param>
    	<init-param>
    		<param-name>param2</param-name>
    		<param-value>1234</param-value>
    	</init-param>
</filter>
<filter-mapping>
    	<filter-name>Filter02</filter-name>
    	<url-pattern>/jspEx/Filter02Process.jsp</url-pattern>
</filter-mapping>
// InitParamFilter.class 파일
package filter;

import java.io.IOException;
import java.io.PrintWriter;
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 InitParamFilter implements Filter {
	private FilterConfig fc = null;
	@Override
	public void init(FilterConfig fc) throws ServletException{
		System.out.println("Filter02 초기화");
		this.fc = fc;
	}
	@Override
		public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("Filter02 수행");
		
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
		
		String param1 = fc.getInitParameter("param1");
		String param2 = fc.getInitParameter("param2");
		
		String msg;
		
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter writer = response.getWriter();
		
		if(id.equals(param1) && passwd.equals(param2)) {
			msg="관리자 로그인 성공";
		} else {
			msg = "관리자 로그인 실패";
		}
		writer.println(msg);
		//다음 필터로 가라 chain연결
		chain.doFilter(request, response);
	}
	
	@Override
	public void destroy() {
		System.out.println("Filter02 해제");
	}
	
}
<!-- 테스트용 Filter02.jsp 파일 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="Filter02Process.jsp" method="post">
		<p>아이디 : <input type="text" name="id"></p>
		<p>비밀번호 : <input type="text" name="passwd"></p>
		<p><input type="submit" value="전송"></p>
	</form>
</body>
</html>
<!-- 로그인 처리 페이지 Filter02Process.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
	%>
	<p>입력된 id값 : <%=id %></p>
	<p>입력된 passwd값 : <%=passwd %></p>
</body>
</html>

 

로그 파일 생성 예시

더보기
// web.xml 파일에 코드
<filter>
    	<filter-name>Filter02_2</filter-name>
    	<filter-class>filter.LogFileFilter</filter-class>
    	<init-param>
    		<param-name>fileName</param-name>
    		<param-value>D:\\Ecom_Work_js\\logs\monitor.log</param-value>
    	</init-param>
    </filter>
    <filter-mapping>
    	<filter-name>Filter02_2</filter-name>
    	<url-pattern>/jspEx/Filter02Process.jsp</url-pattern>
</filter-mapping>
//로그 파일 필터
package filter;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

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 LogFileFilter implements Filter {
	PrintWriter writer;
	
	@Override
	public void init(FilterConfig fc) throws ServletException{
		String fileNm = fc.getInitParameter("fileName");
		if(fileNm==null)
			throw new ServletException("로그 파일의 이름을 찾을 수 없습니다.");
		try {
			//fileName에 해당하는 파일을 가져와서 출력용 파일로 오픈 하기
			writer = new PrintWriter(new FileWriter(fileNm, true), true);
		} catch(IOException e) {
			throw new ServletException("로그 파일을 열 수 없습니다.");
		}
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		writer.printf("현재 일시 : %s %n", getCurrentTime());
		String clientAddr = request.getRemoteAddr();
		writer.printf("클라이언트 주소 : %s %n", clientAddr);
		
		chain.doFilter(request, response);
		String contentType = response.getContentType();
		writer.printf("문서의 콘텐츠 유형 : %s %n", contentType);
		writer.println("--------------------------------");
	}
	private Object getCurrentTime() {
		DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(System.currentTimeMillis());
		return format.format(calendar.getTime());
	}

	@Override
	public void destroy() {
		// 오픈된 파일을 반드시 닫기 위해 실행
		writer.close();
	}		
	
}
<!-- 테스트용 Filter02.jsp 파일 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="Filter02Process.jsp" method="post">
		<p>아이디 : <input type="text" name="id"></p>
		<p>비밀번호 : <input type="text" name="passwd"></p>
		<p><input type="submit" value="전송"></p>
	</form>
</body>
</html>
<!-- 로그인 처리 페이지 Filter02Process.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		String id = request.getParameter("id");
		String passwd = request.getParameter("passwd");
	%>
	<p>입력된 id값 : <%=id %></p>
	<p>입력된 passwd값 : <%=passwd %></p>
</body>
</html>