HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/
Spring
Spring
/
🧲
Filter
🧲

Filter

FilterFilter Life CycleFilter ChainFilter matching patternFilter 예제 코드ContentCachingRequestWrapper

Filter

[참고] Servlet-Containers and Spring Framework
notion image
  • Filter란 Web Application에서 관리되는 영역으로써 Spring Boot Framework에서 Client로부터 오는 요청/응답에 대해서 최초/최종 단계의 위치에 존재함(ObjectMapper가 적용되기도 전임. 객체 매핑 전)
  • 이를 통해서 요청/응답의 정보를 변경하거나 Spring에 의해서 데이터가 변환되기 전의 순수한 Client의 요청/응답 값을 확인 할 수 있음
  • 유일하게 ServletRequest, ServletResponse의 객체를 변환 할 수 있음
  • 필터는 다수의 서블릿이나 다른 Java EE 웹 컴포넌트가 어떤 일반적인 기능, 예를 들어 인증, 로깅, 암호화와 같은 기능을 적용하고자 할 때 사용됨
    • Authentication Filters
    • Logging and Auditing Filters
    • Image conversion Filters
    • Data compression Filters
    • Encryption Filters
    • Tokenizing Filters
    • Filters that trigger resource access events
    • XSL/T filters
    • Mime-type chain Filter
  • 이를 선/후 처리 함으로써 Service business logic과 분리시킴
  • Filter가 제일 앞단에 있고 그다음이 Intercepter, 그 다음이 AOP 순서대로 적용이 됨
  • Filter는 java.servlet.Filter 를 구현해야 함
@WebFilter("/*") public class LoggingFilter implements Filter { private FilterConfig filterConf = null; public void init(FilterConfig filterConfig) { this.filterConf = filterConf; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException { String userAddy = request.getRemoteHost(); filterConf. getServletContext().log("Visitor User IP: " + userAddy); chain.doFilter(request, response); } @Override public void destroy() { throw new UnsupportedOperationException("Not supported yet.");} }

Filter Life Cycle

  1. 서블릿 컨테이너에 의해 필터 생성
      • Call constructer
      • Call init() method
  1. 각 요청 응답 마다 doFilter() 적용
  1. 서블릿 컨테이너가  destroy() 를 호출함. (컨테이너가 꺼질 때)

Filter Chain

  • 필터는 그 다음 필터를 호출하기 위해 필터 체인을 이용함
    • 여러 필터가 있을 때, 실행 순서는 web.xml의 configuration에 따름
    • 모든 필터와 targe resource는 하나의 스레드에 있게 됨
    • 모든 필터는 하나의 공통된 요청 객체를 공유함

Filter matching pattern

  • URL 패턴은 US-ASCII 문자의 부분집합을 포함함. 다른 값들은 escape처리 되어야함
  • 필터는 URL만 고려해서 해당 필터를 적용함
    • Exact matching
    • Path matching /admin/*
    • Type matching .css

Filter 예제 코드

import java.servlet.*; @Slf4j @Componenet // 만약 특정한 api endpoint에 대해서만 filter를 적용하고 싶을때 Component지우고 // @WebFilter(urlPatterns="/api/user/*") // 그리고 @SpringBootApplication 에 @ServletComponentScan 붙여주기 public class GlobalFilter implements Filter{ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{ // 전처리 HttpServletRequest httpServletRequest = (HttpServletRequest)request; HttpServletResponse httpServletResponse = (HttpServletResponse) response; String url = httpServletRequest.getRequestURI(); BufferedReader br = httpServletRequest.getReader(); br.lines().forEach(line ->{ log.info("url : {}, line : {}", url, line); }); // 근데이렇게 하면 Controller에서 바디를 더이상 읽지를 못함 // HttpServletRequest -> ContentCachingRequestWrapper // HttpServletResponse -> ContentCachingResponseWrapper chain.doFilter(request, response); // 이 과정이 진행되면 response가 만들어짐 // 후처리 String reqContent = new String(httpServletRequest.getContentAsByteArray()); log.info("request url : {}, request body : {}", url, reqContent); String resContent = new String(httpServletResponse.getContentAsByteArray()); int httpStatus = httpServletResponse.getStatus(); httpServletResponse.copyBodyToResponse(); // 앞에서 읽어서 반환이 안됨.복사해주어야함 } }

ContentCachingRequestWrapper

  • request 데이터가 읽히면 해당 데이터의 byte array를 ContentCachingRequestWrapper에 저장해두고 해당 byte array를 계속 반환함(데이터를 여러번 읽는 것이 아님!!. 데이터는 한번만 읽고 byte array를 반환하는것)
    • 그래서 데이터가 읽혀야지만 getContentAsByteArray() 로 데이터 반환이 가능
  • https://dncjf64.tistory.com/329 : Spring Filter에서 requests Body 가공하기
    • 이거 나중에 조금 더 파보기!