Recent Posts
Recent Comments
Link
11-17 02:31
Today
Total
관리 메뉴

삶 가운데 남긴 기록 AACII.TISTORY.COM

필터 Filter 본문

DEV&OPS/Java

필터 Filter

ALEPH.GEM 2022. 6. 15. 18:15

필터

필터는 서블릿 2.3부터 추가되었습니다.

서블릿이 실행되기 전과 후에 필터링 기능 및 추가 기능을 수행할 수 있습니다.

예를 들어 로그 기록이나 한글 처리 같은 기능을 추가 할 수 있습니다.

기존 예제에서는 일일이 서블릿에서 한글 처리를 지정해줬지만 필터에서 일괄적으로 설정할 수 있습니다.

또한 하나의 서블릿에 필터를 여러개 지정해줄 수 있습니다.

필터는 javax.servlet.Filter를 상속 받아서 구현합니다.

init()는 필터 객체가 생성될 때 한 번 만 호출되는 메소드입니다.

destroy()는 필터 객체가 제거될 때 한 번 만 호출되는 메소드입니다.

doFilter()메소드는 필터의 내용을 구현하는 메소드로 web.xml에 필터링 설정한 서블릿이 실행될 때마다 호출됩니다.

 

예제로 FlowFilterOne.java 클래스를 작성합니다.

package net.aacii.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 FlowFilterOne implements Filter {

	@Override
	public void destroy() {
		System.out.println("distroy() 호출: one");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("doFilter() 호출 전: one"); //필터에 해당하는 서블릿이 실행하기 전에 수행할 코드
		chain.doFilter(req,res);
		System.out.println("doFilter() 호출 후: one"); //필터에 해당하는 서블릿이 실행한 후에 수행할 코드
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("init() 호출: one");
	}

}

그리고 새 필터 클래스 FlowFilterTwo.java를 하나 더 작성합니다.

package net.aacii.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 FlowFilterTwo implements Filter {

	@Override
	public void destroy() {
		System.out.println("distroy() 호출: two");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("doFilter() 호출 전: two"); //필터에 필터링된 서블릿이 실행하기 전에 수행하는 코드
		chain.doFilter(req,res);
		System.out.println("doFilter() 호출 후: two"); //필터에 필터링된 서블릿이 실행한 후에 수해하는 코드
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("init() 호출: two");
	}

}

web.xml에 방금 작성한 필터를 등록합니다.

<filter>태그의 위치는 <servlet>태그 위에다 작성합니다.

  	<filter>
  		<filter-name>flow1</filter-name>
  		<filter-class>net.aacii.test.FlowFilterOne</filter-class>
  	</filter>
  	<filter>
  		<filter-name>flow2</filter-name>
  		<filter-class>net.aacii.test.FlowFilterTwo</filter-class>
  	</filter>

<filter-mapping>은 필터링 할 서블릿을 설정해줍니다.

web.xml의 위에서 작성한 <filter> 태그 밑에 <filter-mapping> 태그를 추가해줍니다.

  	<filter-mapping>
  		<filter-name>flow1</filter-name>
  		<url-pattern>/second</url-pattern>
  	</filter-mapping>
  	<filter-mapping>
  		<filter-name>flow2</filter-name>
  		<url-pattern>/*</url-pattern>
  	</filter-mapping>

/second 서블릿은 기존에 작성했던 Second.java를 재활용 합니다.

기존에 작성되어있는 경우 다시 작성 할 필요는 없습니다.

package net.aacii.test;

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;

@WebServlet("/second")
public class Second extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	//GET방식 Http request와 response를 처리
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
		//서버 콘솔에 출력
		System.out.println("SecondServlet");
		//response 객체에 한글 인코딩 세팅
		resp.setContentType("text/html;charset=UTF-8");
		//클라이언트 브라우저에 출력
		PrintWriter out = resp.getWriter();
		out.print("<html><head><title>테스트</title></head>");
		out.print("<body><h1>get방식 요청 처리 테스트</h1></body>");
		out.print("</html>");
		out.close();
	}
}

http://localhost:8080/jsp/second  를 실행 후 콘솔 창을 확인해 봅시다.

web.xml 의 <filter-mapping> 태그의 순서를 바꾸면 필터가 실행되는 순서를 바꿀 수 있습니다.

 

필터 체인 객체는 필터와 서블릿을 연결시켜주는 객체로 FlowFilterTwo.java 파일의 chain.doFilter(req, res); 부분을 주석처리하고 다시 테스트를 해보면 필터만 수행되고 해당 서블릿은 실행되지 않는 것을 확인할 수 있습니다.

즉, 콘솔 창에 SecondServlet 이 출력되지 않게되는 것입니다.

 

한글 처리 필터

우선 한글을 입력 받는 html 파일 input1.html, input2.html, input3.html 파일을 작성해보겠습니다.

input1.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>input1.html</title>
</head>
<body>
	<form action="output1" method="post">
		이름: <input type="text" name="pmName">
		<input type="submit" value="제출">
	</form>
</body>
</html>

input2.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>input2.html</title>
</head>
<body>
	<form action="output2" method="post">
		과목: <input type="text" name="pmSubject">
		<input type="submit" value="제출">
	</form>
</body>
</html>

input3.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>input3.html</title>
</head>
<body>
	<form action="output3" method="post">
		학과: <input type="text" name="pmDept">
		<input type="submit" value="제출">
	</form>
</body>
</html>

 

그 다음 각각 html 의 form submit을 처리하는 서블릿 Output1.java, Output2.java, Output3.java 을 작성합니다.

Output1.java

package net.aacii.test;

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;

@WebServlet("/output1")
public class Output1 extends HttpServlet{

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		out.print(req.getParameter("pmName"));
		out.close();
	}

}

Output2.java

package net.aacii.test;

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;

@WebServlet("/output2")
public class Output2 extends HttpServlet{

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		out.print(req.getParameter("pmSubject"));
		out.close();
	}

}

Output3.java

package net.aacii.test;

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;

@WebServlet("/output3")
public class Output3 extends HttpServlet{

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		out.print(req.getParameter("pmDept"));
		out.close();
	}

}

 

그리고 위에서 작성한 FlowFilterTwo.java 파일을 열어서 한글 처리 코드를 추가합니다.

package net.aacii.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 FlowFilterTwo implements Filter {

	@Override
	public void destroy() {
		System.out.println("distroy() 호출: two");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		req.setCharacterEncoding("UTF-8"); 	//request 한글 처리 코드 추가
		System.out.println("doFilter() 호출 전: two");
		chain.doFilter(req,res);
		System.out.println("doFilter() 호출 후: two");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("init() 호출: two");
	}

}

input1.html, input2.html, input3.html 을 각각 테스트해서 한글을 입력하고 submit 했을 때 post request가 한글을 잘 처리하는지 확인해봅시다.

 

FilterConfig

FilterConfig은 init()메소드로 전달 되는 객체로, web.xml에 <filter>태그로 지정한 <filter>태그의 정보를 추출할 목적으로 사용하는 객체입니다.

위의 예제에서 FlowFilterTwo.java 에서 req.setCharacterEncoding("UTF-8"); 을 추가했지만 java를 수정하면 다시 빌드를 해야 하므로 web.xml에 FilterConfig을 이용해 등록하는 것이 더 좋습니다.

web.xml 에서 기존의 <filter> 의 flow2 필터 부분에 아래처럼 <init-param>태그를 추가합니다.

  	<filter>
  		<filter-name>flow2</filter-name>
  		<filter-class>net.aacii.test.FlowFilterTwo</filter-class>
  		<init-param>
  			<param-name>en</param-name>
  			<param-value>UTF-8</param-value>
  		</init-param>
  	</filter>

 그리고 나서 FlowFilterTwo.java 를 아래처럼 수정합니다.

package net.aacii.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 FlowFilterTwo implements Filter {
	String charset;

	@Override
	public void destroy() {
		System.out.println("distroy() 호출: two");
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		req.setCharacterEncoding(charset); 	//web.xml에 등록한 <filter> 태그의 parameter 값을 이용
		System.out.println("doFilter() 호출 전: two");
		chain.doFilter(req,res);
		System.out.println("doFilter() 호출 후: two");
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		System.out.println("init() 호출: two");
		charset = config.getInitParameter("en");
	}

}

 

 

 

@WebFilter 어노테이션

어노테이션을 이용해서 필터를 구현할 수도 있습니다.

1. Filter 인터페이스를 implements해서 Filter 객체를 구현

2. 필터 객체에 @WebFilter 어노테이션을 선언

3. @WebFilter()에 filterName 속성을 추가

4. @WebFilter()에 urlPatterns 속성을 추가

 

@WebFilter()에 인수로 들어가는 주요 속성은 아래와 같습니다.

urlPatterns: 필터링할 URL들을 패턴으로 지정합니다. 

servletNames: 필터링할 서블릿 이름을 지정합니다.

filterName: 등록하는 필터의 이름을 지정합니다.

initParams: 필터에 전달하는 파라메터를 지정합니다.

 

@WebFilter 예제

필터 클래스 FlowFilterThree.java를 새로 작성합니다.

package net.aacii.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;
import javax.servlet.annotation.WebFilter;

@WebFilter(filterName = "timer", urlPatterns="/third")
public class FlowFilterThree implements Filter {

	@Override
	public void init(FilterConfig config) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		long startTime = System.currentTimeMillis();
		chain.doFilter(req,res);
		long endTime = System.currentTimeMillis();
		long executeTime = endTime - startTime;
		System.out.println("수행시간:"+executeTime +"밀리초");
	}	
	
	@Override
	public void destroy() {

	}

}

그리고 필터를 적용할 Third.java 서블릿을 작성합니다.

package net.aacii.test;

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;

@WebServlet("/third")
public class Third extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public Third() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		int i = 1;
		while(i <= 10) {
			out.print("<br>number: "+i);
			i++;
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		out.print("<br>실행완료");
		out.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

http://localhost:8080/jsp/third   를 실행해보면 콘솔창에 수행시간이 필터에 의해 출력되는 것을 확인 할 수 있습니다.

 

 

 

 

 

 

 

728x90

'DEV&OPS > Java' 카테고리의 다른 글

web.xml 서블릿 오류 처리  (0) 2022.06.20
리스너 Listener  (0) 2022.06.20
request 상태 정보 유지  (0) 2022.06.15
세션을 이용한 로그인  (0) 2022.06.14
세션 Session  (0) 2022.06.14