필터는 Java
웹 어플리케이션에서 클라이언트 요청(Request)과 서블릿/리소스 처리 그리고 응답(Response) 사이에 끼어들어 공통 작업을 처리할 수 있는 기능이다.
필터가 할 수 있는 대표적인 일
구조
[클라이언트] 👉 (Filter) 👉 [서블릿/JSP] 👉 (Filter) 👉 [클라이언트]
컨테이너 시작 시 한번 생성 👉 여러 요청을 다중 스레드로 처리
생명 주기 메서드
init(FilterConfig config)
: 초기화 (초기 파라미터 읽기 등)doFilter(ServletRequest, ServletResponse, FilterChain)
: 전/후처리destory()
: 종료 정리package com.example.test.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, SecurityException, ServletException {
req.setCharacterEncoding("UTF-8");
chain.doFilter(req, resp);
}
}
해당 패키지에 filter를 추가한 패키지를 만들고 클래스를 생성한다.
web.xml
에서 선언한 <filter-mapping>
순서대로 실행<filter-mapping>
<filter-name>Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
<filter-mapping>
...
</filter-mapping>
...
...
/*
, /api/*
, *.jsp
등REQUEST
, FORWARD
, INCLUDE
, ERROR
, ASYNC
( 예 : 에러 페이지에도 적용하려면 ERROR
추가)1) 인코딩 필터 (전처리만)
public class CharacterEncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding("UTF-8"); // getParameter 호출보다 먼저!
chain.doFilter(req, resp);
}
}
2) 로깅/타이밍 필터 (전 후처리)
public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
long start = System.currentTimeMillis();
try {
chain.doFilter(req, resp); // 다음 단계로
} finally {
long took = System.currentTimeMillis() - start;
System.out.println("Request took " + took + "ms");
}
}
}
try/finally
로 후처리 보장
3) 인증 필터 (짧게 차단하기)
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
var httpReq = (javax.servlet.http.HttpServletRequest) req;
var httpResp = (javax.servlet.http.HttpServletResponse) resp;
boolean ok = httpReq.getSession(false) != null;
if (!ok) {
httpResp.sendError(401); // 또는 redirect
return; // 체인 중단
}
chain.doFilter(req, resp);
}
}
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.example.test.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
순서가 실행 순서import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(
urlPatterns = "/*",
dispatcherTypes = { DispatcherType.REQUEST, DispatcherType.ERROR } // 필요 시
// asyncSupported = true
)
public class CharacterEncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
chain.doFilter(req, resp);
}
}
XML
없이 한 파일에 정의 (빠르고 직관적)