-
ServletRequest 여러번 읽기 - ContentCachingRequestWrapperSpring Framework 2023. 9. 6. 00:01728x90
개요
Spring에서 request/response를 다루게 되면 HttpServletRequest/HttpServletResponse를 사용합니다.
이때 최상위 인터페이스는 ServletRequest이며 getInputStream의 경우에는 한 번만 읽을 수 있습니다.
만약 이미 한번 request값을 읽고, 컨트롤러에서 @RequestBody로 2번 읽으려 한다면 HttpMessageNotReadableException가 발생하게 됩니다.
또는 이미 Reader를 사용했다면 다음과 같은 예외 메시지가 나타납니다.
java.lang.IllegalStateException: getInputStream() has already been called for this request
이때 Sprinrg의 ContentCachingRequestWrapper를 활용하여 해결할 수 있습니다.
ContentCachingRequestWrapper
Spring Framework에서 제공하는 클래스로, HTTP 요청의 내용을 캐싱하여 여러 번 접근할 수 있도록 도와주는 래퍼클래스입니다.
주로 로깅, 디버깅 등의 목적으로 활용됩니다.
public byte[] getContentAsByteArray() { return this.cachedContent.toByteArray(); }
getContentAsByteArray 메서드를 통해 바디값을 재활용 할 수 있습니다.
request 말고 response를 여러 번 사용하고 싶다면 ContentCachingResponseWrapper 클래스를 활용할 수 있습니다.
ContentCachingRequestWrapper를 활용하여 Filter에서 로깅찍어보기
@Component class GlobalFilter: Filter { override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain?) { val contentCachingRequestWrapper = ContentCachingRequestWrapper(request as HttpServletRequest) val contentCachingResponseWrapper = ContentCachingResponseWrapper(response as HttpServletResponse) chain!!.doFilter(contentCachingRequestWrapper,contentCachingResponseWrapper) val url = contentCachingRequestWrapper.requestURI val content = String(contentCachingRequestWrapper.contentAsByteArray) println("url: $url, body: $content") } }
참고자료
https://ok-vamos.tistory.com/79
'Spring Framework' 카테고리의 다른 글
SpringApplicationRunner란? (+ 동작과정) (0) 2023.09.08 놓치기 쉽지만 중요한 @Transactional Rollback (1) 2023.09.07 Json 파싱시 없는 필드 무시(@JsonIgnoreProperties) (0) 2023.08.31 Spring 트랜잭션 외부 API 호출 rollback (2) 2023.08.28 feign client ErrorDecoder 분석 (0) 2023.08.25