🔔😁🎅🤔
Filter란 Web Application에서 관리되는 영역으로써 spring Boot 에서 Client로 부터 오는 요청/응답에 대해서 최초/최종 단계의 위치에 존재하며, 이를 통해서 요청/응답의 정보를 변경하거나,Spring에 의해서 데이터가 변환되기 전의 순수한 Client의 요청/응답 값을 확인 할 수 있다.
유일하게 ServletRequest,ServletResponse 의 객체를 변환 할 수 있다.
주로 request/response 의 Logging 용도로 활용하거나, 인증과 관련된 Logic들을 헤당 Fliter에서 처리 한다.
이를 선/후 처리 함으로써 Service business logic과 분리 시킨다.
AOP는 객체로 Mapping 되었기때문에 spring에 들어왔기 때문에 순수하지 않다는 차이점이 있다.
Filter -->> DispatcherServlet-->>HandlerInterceptor-->>AOP동작
그림으로 보면
User.class 만들고 Apicontroller셋팅하고
@Slf4j
@Component //Spring Bean으로 관리되어야함
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);
});
}
}
이렇게 필터를 걸고 slf4j를 사용하여 로그를 찍으면
이렇게 잘 찍힌다.
Filter에서 BufferedReader 를 사용하면
BufferedReader특성상 내용을 한번 읽으면 그내용을 뒤에서 못읽는다 즉 사라진다!!!
ContentCachingRequestWrapper안에있는 ByteArrayOutputStream에 내용을 미리 담아두는데 뒤에서 누가 읽을때 여기 담겨진 내용들을 뒤에서 읽을수 있게 해준다.
public class GlobalFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//전처리
ContentCachingRequestWrapper httpServletRequest = new ContentCachingRequestWrapper((HttpServletRequest) request);
ContentCachingResponseWrapper httpServletResponse = new ContentCachingResponseWrapper((HttpServletResponse) response);
//이렇게 한다고 해도 Byte의 길이만 설정해 두고 컨탠츠들은 복사하지 않는다 그래서 doFilter 다음에 실행시킨다.
chain.doFilter(httpServletRequest, httpServletResponse);
//후처리
String url = httpServletRequest.getRequestURI();
String reqContent = new String(httpServletRequest.getContentAsByteArray());
log.info("request url : {}, request body : {}", url, reqContent);
String resContent = new String(httpServletResponse.getContentAsByteArray());
int httpStatus = httpServletResponse.getStatus();
//Response도 마찬가지로 한번 읽으면 사라진다. 그래서 다시 채워줘야한다.ㅉ
httpServletResponse.copyBodyToResponse(); //다시한번 더 바디를 채워준다.
log.info("response status : {}, responseBody : {}", httpStatus, resContent);
}
}
@Slf4j
@WebFilter(urlPatterns = "/api/user/*")
@Component //Spring Bean으로 관리되어야함
public class GlobalFilter implements Filter {
이렇게 해서Filter로 로그남기기 끝