삶 가운데 남긴 기록 AACII.TISTORY.COM
필터 Filter 본문
필터
필터는 서블릿 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 를 실행해보면 콘솔창에 수행시간이 필터에 의해 출력되는 것을 확인 할 수 있습니다.
'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 |