필터 (Filter)
- 클라이언트와 서버 사이에서 request와 response 객체를 먼저 받아 사전/사후 작업 등 공통적으로 필요한 부분을 처리하는 것
- 클라이언트의 요청이 웹 서버의 서블릿, JSP, HTML 페이지 같은 정적 리소스에 도달하기 전과, 반대로 정적 리소스에서 클라이언트로 응답하기 전에 필요한 전처리를 가능하게 함
- 필터는 HTTP요청과 응답을 변경할 수 있는 코드로 재사용 가능
- 클라이언트와 정적 리소스 사이에 여러 개의 필터로 이루어진 필터 체인을 제공하기도 함
web.xml
- <filter>
- <filter-name> 이름 설정
- <filter-class> 자바 클래스 이름 설정
- <init-param> 매개변수와 값을 설정
- 자바에서 파라미터 값 가져올 때
- this.filterConfig.getInitParameter("파라미터이름");
- <filter-mapping>
- <filer-name> 필터이름 설정
- <url-pattern> URL 패턴을 설정
.
.
<!-- Filter 인터페이스의 구현 클래스 -->
<filter>
<filter-name>Filter01</filter-name>
<filter-class>filter.AuthenFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter01</filter-name>
<url-pattern>/ch12/filter01_process.jsp</url-pattern>
</filter-mapping>
.
.
AuthenFilter.java
- 필터 인터페이스
- init()
- doFilter()
- destory()
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 AuthenFilter implements Filter {
// 필터 시작 초기화
@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 {
request.setCharacterEncoding("UTF-8");
System.out.println("Filter01수행");
// 필터가 여러개가 있을 때 request, response 객체를 전달해줌
chain.doFilter(request, response);
}
// 필터 종료하기 전에 호출
@Override
public void destroy() {
System.out.println("Filter01 해제..");
}
}
filter01.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 폼페이지 -->
<!--
요청URI : /ch12/filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<form action="/ch12/filter01_process.jsp">
<p>이름 : <input type="text" name="name" placeholder="이름"></p>
<p><input type="submit" value="전송"></p>
</form>
</body>
</html>
filter01_process.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 폼페이지 -->
<!--
요청URI : /ch12/filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<%
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
%>
<h3>입력된 name 값 : <%=name %></h3>
</body>
</html>
필터 처리로 매개변수와 값을 전달 - param
web.xml
<filter>
<filter-name>Filter02</filter-name>
<filter-class>filter.InitParamFilter</filter-class>
<!--
매개변수=매개변수 값
InitParamFilter 클래스의 init 메서드로 던져짐
param1=admin¶m2=java -->
<init-param>
<param-name>param1</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>java</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter02</filter-name>
<url-pattern>/ch12/filter02_process.jsp</url-pattern>
</filter-mapping>
InitParamFilter.java
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 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 {
request.setCharacterEncoding("UTF-8");
System.out.println("Filter02 수행");
String id = request.getParameter("id");
String pw = request.getParameter("pw");
System.out.println(id+" "+pw);
String param1 = this.filterConfig.getInitParameter("param1");
String param2 = this.filterConfig.getInitParameter("param2");
String message = "";
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
if(id.equals(param1)&&pw.equals(param2)) {
message = "로그인 성공!";
} else {
message = "로그인 실패!!!!";
}
out.println(message);
// 연속적으로 필터가 있으면 다음 필터로 제어를 넘겨줌(request, response)
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("Filter02 해제..");
}
}
filter02.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 폼페이지 -->
<!--
요청URI : /ch12/filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<form action="/ch12/filter02_process.jsp">
<p>아이디 : <input type="text" name="id" placeholder="아이디"></p>
<p>비밀번호 : <input type="password" name="pw" placeholder="비밀번호"></p>
<p><input type="submit" value="전송"></p>
</form>
</body>
</html>
filter02_process.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 폼페이지 -->
<!--
요청URI : /ch12/filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<%
request.setCharacterEncoding("UTF-8");
String id = request.getParameter("id");
String pw = request.getParameter("pw");
%>
<h3>입력된 id 값 : <%=id %></h3>
<h3>입력된 pw 값 : <%=pw %></h3>
</body>
</html>
필터로 로그 기록
web.xml
<filter>
<filter-name>Filter03</filter-name>
<filter-class>filter.LogFileFilter</filter-class>
<!--
매개변수=매개변수 값
InitParamFilter 클래스의 init 메서드로 던져짐
param1=admin¶m2=java -->
<init-param>
<param-name>filename</param-name>
<param-value>c:\\logs\\monitor.log</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter03</filter-name>
<url-pattern>/ch12/filter03_process.jsp</url-pattern>
</filter-mapping>
LogFileFilter.java
package filter;
import java.io.File;
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;
import javax.servlet.http.HttpServletRequest;
public class LogFileFilter implements Filter {
//파일로 만들어야 하므로 파일객체를 전역변수 형태로 선언
PrintWriter writer;
//초기화
/*
<init-param>
<param-name>filename</param-name>
<param-value>c:\\logs\\monitor.log</param-value>
</init-param>
알기쉽게 설명 : ?filename=c:\\logs\\monitor.log
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String filename =
filterConfig.getInitParameter("filename");//c:\\logs\\monitor.log
//로그를 파일로 저장하기 위해 초기화 작업 수행
//filename => c:\\logs\\webmarket.log
// String filename = "c:\\logs\\monitor.log";
try {
//FileWriter(String fileName, boolean true/false)
//1) true : 기존 내용에 새로운 내용이 추가(append)
//2) false : 기존 내용을 지우고 덮어쓰기(overwrite)
//PrintWriter(출력대상, boolean true/false)
//1) true : Auto flush -> writer.flush()를 생략함
//2) false : Auto flush 안함
this.writer = new PrintWriter(new FileWriter(filename,true),true);
//monitor.log파일이 없으면 자동 생성
//이렇게 하겠다라고 설계
File file = new File(filename);
if(!file.exists()) {//설계상의 파일이 실제로는 없으면..
//설계대로 파일을 생성
file.createNewFile();
writer.println(file.getAbsolutePath() + " 파일이 생성되었습니다.");
}else {//monitor.log 파일이 있다면..
System.out.println(file.getAbsolutePath() + " 파일이 생성되어 있습니다.");
}
}catch(IOException e) {
throw new ServletException("로그 파일을 열 수 없습니다.");
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response
, FilterChain chain)
throws IOException, ServletException {
writer.println("접속한 클라이언트 IP : " + request.getRemoteAddr());
//시스템 현재 시간(시작시간)
long start = System.currentTimeMillis();
writer.println("접근한 URL 경로 : " + getURLPath(request));
writer.println("요청 처리 시작 시각 : " + getCurrentTime());//2024/07/15 17:23:27
//필터가 연속적으로 있다면 다음 필터로 제어 및 요청(request)/응답(response) 정보를 넘겨줌
chain.doFilter(request, response);
//시스템 현재 시간(종료시간)
long end = System.currentTimeMillis();
writer.println("요청 처리 종료 시각 : " + getCurrentTime());
writer.println("요청 처리 소요 시간 : " + (end - start) + "ms");//1000분의 1초
writer.println("=======================");
}
//종료
@Override
public void destroy() {
//파일 객체를 닫아줌. 메모리에서 제거
writer.close();
}
//접근한 URL 경로 리턴 메소드
// http://localhost/ch11/readParameterNoErrorPage.jsp?name=개똥이
private String getURLPath(ServletRequest request) {
//HttpServletRequest 인터페이스 는 ServletRequest 인터페이스를 상속받음
HttpServletRequest req;
//currentPath : URL경로 => http://localhost/ch11/readParameterNoErrorPage.jsp
String currentPath = "";
//queryString : 요청파라미터 => name=개똥이
String queryString = "";
//instanceOf 연산자는 객체가 어떤 클래스인지, 어떤 클래스를 상속받았는지 확인하는 데 사용됨
if(request instanceof HttpServletRequest) {
//자식 = (cast)부모
req = (HttpServletRequest)request;
currentPath = req.getRequestURI();//http://localhost/ch11/readParameterNoErrorPage.jsp
System.out.println("currentPath : " + currentPath);
queryString = req.getQueryString();//name=개똥이
System.out.println("queryString : " + queryString);
//삼항연산자
queryString = queryString == null?"":"?"+queryString;
}
//http://localhost/ch11/readParameterNoErrorPage.jsp?name=개똥이
return currentPath + queryString;
}//end getURLPath()
//현재 시간을 얻어오는 메소드
private String getCurrentTime() {
//2023/03/31 17:29:12
DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
//캘린더 객체 생성(싱글톤 : 메모리에 1번 생성하고 전역변수처럼 사용)
Calendar calendar = Calendar.getInstance();
//톰켓서버에서 제공해주는 시스템 현재 시간을 구해서 캘린더 객체에 세팅
calendar.setTimeInMillis(System.currentTimeMillis());
//2023/03/31 17:29:12 이러한 포맷을 준수하면서 리턴
return formatter.format(calendar.getTime());
}
}
filter03.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 폼페이지 -->
<!--
요청URI : /ch12/filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<form action="/ch12/filter03_process.jsp">
<p>아이디 : <input type="text" name="id" placeholder="아이디"></p>
<p>비밀번호 : <input type="password" name="pw" placeholder="비밀번호"></p>
<p><input type="submit" value="전송"></p>
</form>
</body>
</html>
filter03_process.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 폼페이지 -->
<!--
요청URI : /ch12/filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<%
request.setCharacterEncoding("UTF-8");
String id = request.getParameter("id");
String pw = request.getParameter("pw");
%>
<h3>입력된 id 값 : <%=id %></h3>
<h3>입력된 pw 값 : <%=pw %></h3>
</body>
</html>