필터
필터(Filter)는 서블릿이나 JSP에 요청이 도달하기 전에 요청과 응답을 가로채서 처리하는 컴포넌트이다.
필터는 요청을 수정, 응답을 변경, 로깅 및 인증 등의 작업을 수행할 수 있다.

필터는 클라이언트와 자원사이에 여러 개의 필터가 모여 하나의 체인(Chain)을 형성할 수도 있다.
WAS 서버에 필터를 설정하는 방법은 web.xml 파일에서 설정하거나 자바 코드 측에 애너테이션을 사용해 설정할 수 있는 두 가지 방법이 존재한다.
예시코드 - web.xml 파일에 설정
<filter>
<filter-name>LoggingFilter</filter-name>
<filter-class>com.example.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
예시코드 - Java 파일에 설정
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class LoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 필터 초기화 작업
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 요청 전 처리
System.out.println("Request received at " + new java.util.Date());
chain.doFilter(request, response); // 다음 필터나 서블릿으로 요청 전달
// 응답 후 처리
System.out.println("Response sent at " + new java.util.Date());
}
@Override
public void destroy() {
// 필터 종료 작업
}
}
필터의 주요 기능
- 요청 및 응답의 전처리 및 후처리
- 로깅 처리
- 인증 및 권한 부여
- 데이터 압축
서블릿 리스너
리스너란
컨테이너에서 발생하는 이벤트를 모니터링하다가 특정 이벤트가 발생하면 실행되는 특수한 서블릿으로, '이벤트 리스너'라고도 한다. 즉, 리스너는 웹 애플리케이션에서 특정 사건이 일어났을 때 그것을 알아차리고 적절한 처리를 하는 역할을 한다. 예를 들어 애플리케이션이 시작되거나 종료될 때 발생하는 사건이나 사용자가 웹사이트에 로그인하거나 로그아웃하는 등의 사건 또는 사용자가 웹페이지를 요청하거나 특정 작업을 수행할 때 발생하는 사건 등 리스너는 이러한 다양한 사건들을 감지하고, 필요한 작업을 자동으로 수행하는 중요한 역할을 한다.

WAS 서버에 리스너를 설정하는 방법은 서블릿과 마찬가지로 web.xml 파일에서 설정하거나 자바 코드측에 애노테이션을 사용하여 설정하는 방법이 존재한다.
web.xml 파일에 설정 방식
<web-app ..>
<listener>
<listener-class>com.example.AppContextListener</listener-class>
</listener>
</web-app>
자바코드 애노테이션 설정 방식
@WebListener
public class AppContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// 애플리케이션 시작 시 처리 작업
System.out.println("Application started at " + new java.util.Date());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// 애플리케이션 종료 시 처리 작업
System.out.println("Application stopped at " + new java.util.Date());
}
}
리스너의 주요 기능
- 애플리케이션 시작 및 종료 감지
- 세션 생성 및 소멸 감지
- 요청 시작 및 종료 감지
- 애플리케이션 속성 변경 감지
프로젝트 생성 - filterListenerEx
package com.tenco.filters;
import java.io.IOException;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
/**
* 1. Filter 구현
* 2. URL 패턴 설정 (web.xml 파일에서 설정해 볼 예정)
*/
public class IPBlockFilter implements Filter {
// 192.168.0.48 : 내 아이피
// http://192.168.0.48:8080/fl/home
// 차단할 IP 대역의 접두사
private static final String BLOCKED_IP_PREFIX = "192.168.0.25";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("IPBlockFilter 초기화");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 서블릿으로 보내기 전 전처리 - 요청자의 IP 확인 (요청자의 정보는 request 객체 안에 담긴다.)
String remoteIP = request.getRemoteAddr();
System.out.println("Request from IP : " + remoteIP);
// 차단 시킬 코드를 작성
if(remoteIP.startsWith(BLOCKED_IP_PREFIX)) {
System.out.println("차단할 IP가 여기서 걸림");
response.setContentType("text/plain; charset=UTF-8");
response.getWriter().println("Access Denied !");
response.getWriter().println("통과할 수 없습니다.");
return;
}
chain.doFilter(request, response);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
id="WebApp_ID" version="6.0">
<display-name>filterListenerEx</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>default.htm</welcome-file>
</welcome-file-list>
<filter>
<filter-name>IPBlockFliter</filter-name>
<filter-class>com.tenco.filters.IPBlockFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>IPBlockFliter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<description></description>
<display-name>HomeServlet</display-name>
<servlet-name>HomeServlet</servlet-name>
<servlet-class>com.tenco.controller.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HomeServlet</servlet-name>
<url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>
</web-app>
리스너
리스너는 특정 이벤트가 발생했을 때 이를 감지하고, 그에 대응하는 작업을 수행하는 자바 객체이다.
리스너는 서블릿 컨테이너에서 발생하는 다양한 이벤트를 처리할 수 있다.
사용하는 이유
리스너는 웹 애플리케이션의 상태 변화 (예: 시작, 종료, 세션 생성 및 소멸)를 감지하여 다음과 같은 작업을 수행할 수 있도록 도와준다.
- 초기화 작업 (애플리케이션 시작 시 필요한 리소스 로드)
- 정리 작업 ( 애플리케이션 종료 시 리소스 해제)
- 세션 관련 작업 (로그인/로그아웃 로깅, 세션 속성 변경 감지)
주요 리스너 인터페이스
- ServletContextListener: 애플리케이션 시작 및 종료 이벤트를 처리
- HttpSessionListener: 세션 생성 및 소멸 이벤트를 처리
- ServletRequestListener: 요청 객체의 생성 및 소멸 이벤트를 처리
AppLifecycleListener
package com.tenco.listeners;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
/**
* 리스너 사용해보기 ServletContext 구현 어떠한 이벤트가 발생했을때 동작하는 트리거 > web.xml 파일과 어노테이션 기반으로
* 설정가능
*/
public class AppLifecycleListener implements ServletContextListener {
private static final Logger logger = Logger.getLogger(AppLifecycleListener.class.getName());
// 만들기
private String timeFormat() {
// yyyy-MM-dd HH:mm:ss
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return formatter.format(new Date());
}
// 애플케이션의 시작을 로그나 파일로 남겨야 될 상황에 사용한다 > 라고 가정
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("---------------------------");
logger.info("웹 애플리케이션 시작됨 >>>" + System.currentTimeMillis());
System.out.println("---------------------------");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("---------------------------");
logger.info("웹 애플리케이션 종료됨 >>>" + System.currentTimeMillis());
System.out.println("---------------------------");
}
}
MySessionListener
package com.tenco.listeners;
import java.util.logging.Logger;
import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
/**
* 세션이 생성될 때 / 감지될 때 HttpSessionListener 리스너 사용한다.
*/
@WebListener
public class MySessionListener implements HttpSessionListener {
private static final Logger logger = Logger.getLogger(MySessionListener.class.getName());
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("----------------------");
// 세션 생성 시 실행 됨
logger.info("새로운 세션이 생성 됨 : " + se.getSession().getId());
se.getSession().setAttribute("loginTime", System.currentTimeMillis());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// 세션 소멸 시 실행 됨
Long loginTime = (Long) se.getSession().getAttribute("loginTime");
// 세션 생성 시 실했했던 키 값을 동일하게 넣으면 생성했던 시간을 담을 수 있다.
Long logoutTime = System.currentTimeMillis();
if(loginTime != null) {
Long sessionDurationMs = logoutTime - loginTime; // 밀리초 단위
double sessionDurationSec = sessionDurationMs / 1000.0; // 초 단위로 변환
System.out.println("세션 지속 시간 : " + sessionDurationSec);
}
System.out.println("-----------------------");
}
}
'Java' 카테고리의 다른 글
| JSP 라이프사이클 (0) | 2024.07.05 |
|---|---|
| JSP(Java Server Pages) (1) | 2024.07.05 |
| server.xml과 context.xml 그리고 web.xml 파일 (0) | 2024.07.04 |
| 서블릿과 서블릿 컨텍스트 (0) | 2024.07.04 |
| Get, Post 요청 방식 (1) | 2024.07.03 |