반응형
필터
: 클라이언트와 서버 사이에서 request와 response 객체를 먼저 받아 공통적으로 필요한 부분을 처리하는 것
요청, 응답할 때 각각의 전처리 기능을 함
HTTP 요청과 응답을 변경할 수 있는 코드로 재사용 가능
ex) 한글 처리 필터, 로그 처리 필터, 시큐리티 필터 등
- 필터의 기능
필터 | 기능 |
Request 필터 | 인증(사용자 인증) 요청 정보를 로그 파일로 작성 암호화 인코딩 작업 |
Response 필터 | 응답 결과 데이터 압축 응답 결과에 내용 추가/수정 총 서비스 시간 측정 |
Filter 인터페이스
: 필터 기능을 구현하는 데 핵심적인 역할
클라이언트와 서버의 리소스 사이에 위치한 필터의 기능을 제공하기 위해 자바 클래스로 구현해야 함
import javax.servlet.Filter;
public class 클래스 이름 implements Filter
{
생략
}
- Filter 인터페이스 메소드의 종류
메소드 | 설명 |
init(값) | 필터 인스턴스의 초기화 메소드 |
doFilter(값) | 필터 기능 작성 메소드 |
destroy() | 필터 인스턴스의 종료 전에 호출되는 메소드 |
web.xml (하단에 추가)
<!-- Filter 인터페이스의 구현 클래스(필터)를 클라이언트와 서버 사이에 장착해보자 -->
<!-- filter의 filter-name과 filter-mapping의 filter-name이 같아야 함 -->
<filter>
<filter-name>Filter01</filter-name>
<filter-class>filter.AuthenFilter</filter-class>
</filter>
<!-- Filter01로 연결된 필터를 사용할 요청 URL -->
<filter-mapping>
<filter-name>Filter01</filter-name>
<url-pattern>/ch12/filter01_process.jsp</url-pattern>
</filter-mapping>
AuthenFilter.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 AuthenFilter implements Filter{
// 필터 시작. 초기화
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter01 초기화 완료");
}
// 요청파라미터 : {name=개똥이}
// 필터 기능(서비스 로직) 수행
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("filter01.jsp 수행..");
// 요청URI : /ch12/filter01_process.jsp?name=개똥이
String name = request.getParameter("name"); // 개똥이
// 객체/숫자 비교 : ==
// 문자열 비교 : equals
if(name==null || name.equals("")) {
// 응답 메시지를 담아서 서버(톰켓)에서 클라이언트(크롬)로 전달해줌(response객체 활용)
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
String message = "입력된 name 값은 null입니다.";
writer.print(message);
//1. return있으면 : message가 화면에 뜨고
//2. return없으면 : filter01_process.jsp를 찾게됨
return;
}
// 필터가 여러개 있을 때 필터 간에 전달해줌
chain.doFilter(request, response);
}
// 필터 종료 전 호출
@Override
public void destroy() {
System.out.println("filter01해제..");
}
}
- 파라미터에 값 넣을 때
filter01_process.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!--
요청URI : filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<%
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");//개똥이
%>
<p>입력된 name 값 : <%=name%></p>
</body>
</html>
- post로 값 보내기
AuthenFilter.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 AuthenFilter implements Filter{
// 필터 시작. 초기화
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter01 초기화 완료");
}
// 요청파라미터 : {name=개똥이}
// 필터 기능(서비스 로직) 수행
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 한글 깨짐으로 인해 추가해줘야함!!!
request.setCharacterEncoding("UTF-8");
System.out.println("filter01.jsp 수행..");
// 요청URI : /ch12/filter01_process.jsp?name=개똥이
String name = request.getParameter("name"); // 개똥이
// 객체/숫자 비교 : ==
// 문자열 비교 : equals
if(name==null || name.equals("")) {
// 응답 메시지를 담아서 서버(톰켓)에서 클라이언트(크롬)로 전달해줌(response객체 활용)
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
String message = "입력된 name 값은 null입니다.";
writer.print(message);
//1. return있으면 : message가 화면에 뜨고
//2. return없으면 : filter01_process.jsp를 찾게됨
return;
}
// 필터가 여러개 있을 때 필터 간에 전달해줌
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 : filter01_process.jsp
요청파라미터 : {name=개똥이}
요청방식 : post
-->
<form action="filter01_process.jsp" method="post">
<p>이름 : <input type="text" name="name" ></p>
<p><input type="submit" value="전송"></p>
</form>
</body>
</html>
- id와 password 입력 받기
filter02.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!--
요청URI : filter02_process.jsp
요청파라미터 : {id=admin, passwd=java}
요청방식 : post
-->
<form action="filter02_process.jsp" method="post">
<p>아이디 : <input type="text" name="id" required placeholder="아이디"></p>
<p>비밀번호 : <input type="password" name="passwd" required 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 : filter02_process.jsp
요청파라미터 : {id=admin, passwd=java}
요청방식 : post
-->
<% // 스크립틀릿
request.setCharacterEncoding("UTF-8");
// 지역변수
String id = request.getParameter("id");
String passwd = request.getParameter("passwd");
%>
<p>입력된 id 값 : <%=id%></p>
<p>입력된 passwd 값 : <%=passwd%></p>
</body>
</html>
- 로그인으로 변형 (필터 사용)
web.xml (하단에 추가)
<!-- URI가 요청되면 해당 필터 서블릿이 실행됨 -->
<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>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;
// filterConfig{param1=admin,param2=java}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter02 초기화");
this.filterConfig = filterConfig;
}
/*
요청URI : filter02_process.jsp
요청파라미터 : {id=admin, passwd=java}
요청방식 : post
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("Filter02 수행");
// 사용자가 입력한 값
String id = request.getParameter("id"); // admin
String passwd = request.getParameter("passwd"); // java
// web.xml 필터 파라미터 값
String param1 = this.filterConfig.getInitParameter("param1"); // admin
String param2 = this.filterConfig.getInitParameter("param2"); // java
String message = "";
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
if(id.equals(param1) && passwd.equals(param2)) {
message = "로그인 성공!";
} else {
message = "로그인 실패";
}
// message 값이 response객체에 들어감
writer.println(message);
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("Filter02 해제..");
}
}
쇼핑몰 로그인 필터 기능 추가
web.xml (하단에 추가해야 함)
<filter>
<filter-name>LogFileFilter</filter-name>
<filter-class>filter.LogFileFilter</filter-class>
<init-param>
<param-name>filename</param-name>
<param-value>c:\\logs\\webmarket.log</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LogFileFilter</filter-name>
<!-- http://localhost/의 모든 하위 폴더 및 모든 url요청 시 작동 -->
<url-pattern>/*</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;
/*
filterConfig{filename=c:\\logs\\webmarket.log}
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String filename = filterConfig.getInitParameter("filename"); // c:\\logs\\webmarket.log
// 로그를 파일로 저장하기 위해 초기화 작업 수행
// filename => c:\\logs\\webmarket.log
// String filename = "c:\\logs\\webmarket.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 안함 -> writer.flush()를 사용해야함
writer = new PrintWriter(new FileWriter(filename,true),true); // doFilter에서도 쓰기 위해 전역으로 사용함
//webmarket.log 파일이 없으면 자동 생성
//이렇게 하겠다라고 설계
File file = new File(filename);
if(!file.exists()) {//설계상의 파일이 실제 없으면..
//설계대로 파일을 생성
file.createNewFile();
writer.println(file.getAbsolutePath() + " 파일이 생성되었습니다."); // 파일 생성했음을 로그에 추가한다는 뜻
}else {//있으면..
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());
//필터가 연속적으로 있다면 다음 필터로 제어 및 요청(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());
}
}
반응형
'스프링' 카테고리의 다른 글
[스프링] 21장 세션 (1) | 2024.04.18 |
---|---|
[스프링] 20장 과제 (0) | 2024.04.17 |
[스프링] 18장 쇼핑몰 시스템6 (1) | 2024.04.16 |
[스프링] 17장 예외 처리 (0) | 2024.04.16 |
[스프링] 16.5장 과제 (0) | 2024.04.15 |