필터(filter)
클라이언트와 서버 사이에서 request와 response 객체를 먼저 받아 사전/사후
작업 등 공통적으로 필요한 부분을 처리하는 것
필터는 클라이언트 요청이 웹 서버의 서블릿. JSP. HTML 페이지 같은 정적
리소스에 도달하기 전과. 반대로 정적 리소스에서 클라이언트로 응답하기 전
에 필요한 전처리를 가능하게 함.
필터는 HTTP 요청과 응답을 변경할 수 있는 코드로 재사용이 가능합니다.
한편 클라이언트와 정적 리소스 사이에 여러 개의 필터로 이루어진 필터 체인을
제공하기도 함
web.xml 파일 구성
필터 예제 - 실제 생성이 되는지 확인
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Chap17_Filter</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter> <!-- 필터태그는 필터를 등록하고 동시에 필터클래스를 지정해야 함 -->
<filter-name>loggingFilter</filter-name>
<filter-class>kr.gov.filter01.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<url-pattern>*.jsp</url-pattern> <!-- *.jsp : 모든 jsp파일을 실행하면 필터가 작동함을 의미함 -->
</filter-mapping>
</web-app>
LoggingFilter.java
package kr.gov.filter01;
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;
/*
* *필터(Filter)
* - 브라우저에서 서블릿에 요청하거나 응답할때 미리 요청이나 응답과 관련된 여러 작업을 처리하는 기능
* - 요청이나 응답시 공통적인 작업을 처리할때 이용됨.
* - 요청필터 : 사용자 인증 및 권한 검사, 요청시 요청 관련 로그 작업, 인코딩 기능
* - 응답필터 : 응답 결과에 대한 암호화 작업, 서비스 시간 측정
*/
public class LoggingFilter implements Filter{
//필터가 생성될 때 단한번 호출됨.
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.err.println("필터 초기화 됨");
}
//요청시마다 필터가 실행되는 메서드
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("요청이 필터에서 처리됨");
chain.doFilter(request, response);
System.out.println("응답이 필터에서 처리됨");
}
//필터가 제거될 때 실행
@Override
public void destroy() {
System.out.println("필터 제거됨");
}
}
filterTest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>필터 테스트 -1</title>
</head>
<body>
<%
System.out.println("JSP 호출됨");
%>
</body>
</html>
폼 페이지에서 전송된 요청 파라미터를 필터로 처리하기 예제
AuthenFilter.java
package kr.gov.filter02;
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{
public AuthenFilter() {
System.out.println("AuthenFilter 생성자 호출");
}
@Override
public void init(FilterConfig filterConfig) 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("")) { //name값이 null이라면 아래 doFilter()는 호출이 되지 않는다.
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("입력된 name은 null입니다.");
return;
}
chain.doFilter(request, response);
System.out.println("filter01.jsp 응답");
}
@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>필터 테스트 -2</title>
</head>
<body>
<form action="filter01_process.jsp" method="post">
<p>이름 : <input type="text" name="name">
<input type="submit" value="전송">
</form>
</body>
</html>
filter01_process.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>필터결과페이지-1</title>
</head>
<body>
<% String name = request.getParameter("name"); %>
<p>입력된 name 값 : <%=name %>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Chap17_Filter</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!--
<filter> 필터태그는 필터를 등록하고 동시에 필터클래스를 지정해야 함
<filter-name>loggingFilter</filter-name>
<filter-class>kr.gov.filter01.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<url-pattern>*.jsp</url-pattern> *.jsp : 모든 jsp파일을 실행하면 필터가 작동함을 의미함
</filter-mapping>
-->
<filter>
<filter-name>filter01</filter-name>
<filter-class>kr.gov.filter02.AuthenFilter</filter-class>
</filter>
<filter-mapping> <!-- 위에 등록한 필터 사용범위를 지정하는 것 -->
<filter-name>filter01</filter-name>
<url-pattern>/filter01_process.jsp</url-pattern> <!-- 반드시 경로지정자 /를 넣도록 함 -->
</filter-mapping>
</web-app>
filter01 실행 - > 값을 넣지 않았을 경우
filter01 실행 - > 값을 넣었을 경우
필터를 사용한 로그인 예제
InitParamFilter.java
package kr.gov.filter03;
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 filterConfig = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter02 초기화");
this.filterConfig = filterConfig;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("filter02 수행");
String id = request.getParameter("id");
String pw = request.getParameter("pw");
//web.xml에서 <initParam>태그로 설정된 값을 받아오는 코드
String param1 = filterConfig.getInitParameter("param1");
String param2 = filterConfig.getInitParameter("param2");
String message;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
if(id.equals(param1) && pw.equals(param2)) {
message = "로그인 성공";
}
else {
message = "로그인 실패";
}
PrintWriter out = response.getWriter();
out.println(message);
chain.doFilter(request, response);
System.out.println("filter02 완료");
}
@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>필터 테스트 -3</title>
</head>
<body>
<form action="filter02_process.jsp" method="post">
<p>아이디 : <input type="text" name="id">
<p>패스워드 : <input type="password" name="pw">
<p> <input type="submit" value="전송">
</form>
</body>
</html>
filter02_process.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>필터결과페이지-2</title>
</head>
<body>
<%
String id = request.getParameter("id");
String pw = request.getParameter("pw");
%>
<p>입력된 id 값 : <%=id %>
<p>입력된 pw 값 : <%=pw %>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Chap17_Filter</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!--
<filter> 필터태그는 필터를 등록하고 동시에 필터클래스를 지정해야 함
<filter-name>loggingFilter</filter-name>
<filter-class>kr.gov.filter01.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<url-pattern>*.jsp</url-pattern> *.jsp : 모든 jsp파일을 실행하면 필터가 작동함을 의미함
</filter-mapping>
-->
<!-- 여러개의 필터태그를 이용하여 해당 클래스를 필터로 지정하게 되면,
모든 필터클래스의 인스턴스가 다 생성되고 init()을 호출하게 된다. -->
<filter>
<filter-name>filter01</filter-name>
<filter-class>kr.gov.filter02.AuthenFilter</filter-class>
</filter>
<filter-mapping> <!-- 위에 등록한 필터 사용범위를 지정하는 것 -->
<filter-name>filter01</filter-name>
<url-pattern>/filter01_process.jsp</url-pattern> <!-- 반드시 경로지정자 /를 넣도록 함 -->
</filter-mapping>
<filter>
<filter-name>filter02</filter-name>
<filter-class>kr.gov.filter03.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>0217</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filter02</filter-name>
<url-pattern>/filter02_process.jsp</url-pattern>
</filter-mapping>
</web-app>
filter02.jsp 실행
필터 log정보 저장 예제
monitor.log 만들기
LogFileFilter.jsp
package kr.gov.filter04;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
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 = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LogFileFilter 초기화");
String filename = filterConfig.getInitParameter("filename");
if(filename == null) { //파일이 없을 경우 filter.log 파일
throw new ServletException("로그 파일의 이름을 찾을 수 없습니다.");
}
/*
* 매개변수로 받는 값이 FileWriter보조스트림을 연결하는데
* true값은 파일을 덮어쓰지말고 이어서 계속 로그기록을 남기기 위한 속성을 정의한 것.
* PrintWiter주스트림의 매개변수 중 true는 autoFlush를 하라는 의미이다.
*/
try {
writer = new PrintWriter(new FileWriter(filename, true), true);
} catch (IOException e) {
e.printStackTrace();
}
}
public String getCurrentTime() {
SimpleDateFormat sFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
return sFormat.format(new Date());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
writer.printf("접속 일시 : %s %n", this.getCurrentTime());
String clienAddr = request.getRemoteAddr(); //요청한 클라이언트 IP 획득
writer.printf("클라이언트 주소 : %s %n", clienAddr);
chain.doFilter(request, response);
String contentType = response.getContentType();
writer.printf("문서 유형 : %s %n", contentType);
String id = request.getParameter("id");
String pw = request.getParameter("pw");
writer.printf("입력된 아이디 : %s %n", id);
writer.printf("입력된 비밀번호 : %s %n", pw);
writer.printf("-----------------------------------------------%n");
}
@Override
public void destroy() {
System.out.println("LogFileFilter 해제");
writer.close();
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Chap17_Filter</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!--
<filter> 필터태그는 필터를 등록하고 동시에 필터클래스를 지정해야 함
<filter-name>loggingFilter</filter-name>
<filter-class>kr.gov.filter01.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<url-pattern>*.jsp</url-pattern> *.jsp : 모든 jsp파일을 실행하면 필터가 작동함을 의미함
</filter-mapping>
-->
<!-- 여러개의 필터태그를 이용하여 해당 클래스를 필터로 지정하게 되면,
모든 필터클래스의 인스턴스가 다 생성되고 init()을 호출하게 된다. -->
<filter>
<filter-name>filter01</filter-name>
<filter-class>kr.gov.filter02.AuthenFilter</filter-class>
</filter>
<filter-mapping> <!-- 위에 등록한 필터 사용범위를 지정하는 것 -->
<filter-name>filter01</filter-name>
<url-pattern>/filter01_process.jsp</url-pattern> <!-- 반드시 경로지정자 /를 넣도록 함 -->
</filter-mapping>
<filter>
<filter-name>filter02</filter-name>
<filter-class>kr.gov.filter03.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>0217</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filter02</filter-name>
<url-pattern>/filter02_process.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>filter03</filter-name>
<filter-class>kr.gov.filter04.LogFileFilter</filter-class>
<init-param>
<param-name>filename</param-name>
<param-value>C:\\workspace-jsp\\log\\monitor.log</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filter03</filter-name>
<url-pattern>/filter02_process.jsp</url-pattern>
</filter-mapping>
</web-app>
위의 filter02_process.jsp 활용함
filter02.jsp실행