복붙노트

[SPRING] Spring 'HandlerMethodArgumentResolver'에서 요청 본문을 여러 번 읽으려면 어떻게해야합니까?

SPRING

Spring 'HandlerMethodArgumentResolver'에서 요청 본문을 여러 번 읽으려면 어떻게해야합니까?

요청 본문에서 값을 추출하고 유효성을 검사하여 특정 주석 매개 변수에 주입하기 위해 RequestMapping 메서드의 일부 매개 변수를 해결하려고합니다.

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                              NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    // 1, get corresponding input parameter from NativeWebRequest
    // 2, validate
    // 3, type convertion and assemble value to return
    return null;
}

가장 큰 문제는 HttpServletRequest (NativeWebRequest에서 가져 오기)가 한 번 이상 입력 스트림 (일부 매개 변수가 요청 본문에 있음)을 읽을 수 없다는 것입니다. 그렇다면 Inputstream / Reader 또는 요청 본문을 두 번 이상 검색하려면 어떻게해야합니까?

해결법

  1. ==============================

    1.필터를 추가하고 현재 HttpServletRequest를 가로 채서 사용자 정의 HttpServletRequestWrapper로 래핑 할 수 있습니다. 사용자 정의 HttpServletRequestWrapper에서 요청 본문을 읽고 캐시 한 다음 getInputStream 및 getReader를 구현하여 캐시 된 값을 읽습니다. 요청을 래핑 한 후 캐시 된 값이 항상 존재하므로 요청 본문을 여러 번 읽을 수 있습니다.

    필터를 추가하고 현재 HttpServletRequest를 가로 채서 사용자 정의 HttpServletRequestWrapper로 래핑 할 수 있습니다. 사용자 정의 HttpServletRequestWrapper에서 요청 본문을 읽고 캐시 한 다음 getInputStream 및 getReader를 구현하여 캐시 된 값을 읽습니다. 요청을 래핑 한 후 캐시 된 값이 항상 존재하므로 요청 본문을 여러 번 읽을 수 있습니다.

    @Component
    public class CachingRequestBodyFilter extends GenericFilterBean {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest currentRequest = (HttpServletRequest) servletRequest;
            MultipleReadHttpRequest wrappedRequest = new MultipleReadHttpRequest(currentRequest);
            chain.doFilter(wrappedRequest, servletResponse);
        }
    }
    

    이 필터 후에는 여러 번 읽을 수있는 wrappedRequest가 모두에게 표시됩니다.

    public class MultipleReadHttpRequest extends HttpServletRequestWrapper {
        private ByteArrayOutputStream cachedContent;
    
        public MultipleReadHttpRequest(HttpServletRequest request) throws IOException {
            // Read the request body and populate the cachedContent
        }
    
        @Override
        public ServletInputStream getInputStream() throws IOException {
            // Create input stream from cachedContent
            // and return it
        }
    
        @Override
        public BufferedReader getReader() throws IOException {
            // Create a reader from cachedContent
            // and return it
        }
    }
    

    MultipleReadHttpRequest를 구현하기 위해 기본적으로 동일한 작업을 수행하는 Spring 프레임 워크에서 ContentCachingRequestWrapper를 살펴볼 수 있습니다.

    이 접근법에는 자체 단점이 있습니다. 우선, 모든 요청에 ​​대해 요청 본문이 적어도 두 번 읽혀지기 때문에 다소 비효율적입니다. 다른 중요한 단점은 요청 본문에 10GB 상당의 스트림이 포함되어 있고 10GB의 데이터를 읽었을 때 더 심해질 수 있으므로 더 많은 검토를 위해이를 메모리로 가져와야한다는 것입니다.

  2. from https://stackoverflow.com/questions/34804205/how-can-i-read-request-body-multiple-times-in-spring-handlermethodargumentresol by cc-by-sa and MIT license