HttpRequest에서 body값 가져오기

단비·2023년 5월 22일
0

학습

목록 보기
59/66

Form Data를 어느 method에 넣느냐에 따라 쿼리파라미터의 위치가 다르다

  • get: url
  • post: body

컨트롤러에서 HttpRequestServlet을 이용하여 body를 출력하려 하면 null값이 출력됨


요청 -> 필터 -> 디스패처 서블릿 -> 인터셉터 -> 컨트롤러로 값을 바인딩 하는 과정에서

Interceptor에서 getInputStream() 을 호출하여 Http Body를 읽으면서 소비하였기 때문에
Controller의 Http Body가 비어있는 것


public void test(HttpServletRequest request) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

위의 코드와 같이 데이터를 추출할 경우 아래와 같이 길이만 출력됨

Http Body = 
Http Body Length = 38




해결 방법

1. HttpServletRequestWrapper 를 상속받는 클래스 생성

  • 한번 읽고 사라지는 HttpBody가 아닌 여러번 계속해서 읽을 수 있도록 구현
  • getInputStream()에서 요청 Http Body를 복사하여 값을 저장하고 반환하는 기능을 재정의
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
    private ByteArrayOutputStream cachedBytes;

    public MultiReadHttpServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (cachedBytes == null)
            cacheInputStream();

        return new CachedServletInputStream(cachedBytes.toByteArray());
    }

    @Override
    public BufferedReader getReader() throws IOException{
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    private void cacheInputStream() throws IOException {
        /* Cache the inputstream in order to read it multiple times. For
         * convenience, I use apache.commons IOUtils
         */
        cachedBytes = new ByteArrayOutputStream();
        IOUtils.copy(super.getInputStream(), cachedBytes);
    }


    /* An input stream which reads the cached request body */
    private static class CachedServletInputStream extends ServletInputStream {

        private final ByteArrayInputStream buffer;

        public CachedServletInputStream(byte[] contents) {
            this.buffer = new ByteArrayInputStream(contents);
        }

        @Override
        public int read() {
            return buffer.read();
        }

        @Override
        public boolean isFinished() {
            return buffer.available() == 0;
        }

        @Override
        public boolean isReady() {
            return true;
        }

        @Override
        public void setReadListener(ReadListener listener) {
            throw new RuntimeException("Not implemented");
        }
    }
}

2. Filter 를 구현하는 클래스 생성

  • 인터셉터에서 Http Body가 소모 되기 전에 필터 단계에서 Http Body를 옮겨 담는 기능을 수행
@Component
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {

        MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request);
        chain.doFilter(multiReadRequest, response);
    }
}

3. 사용

ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);








💡 TIPS

자바에서 개행 문자 지우는 법 (replace)

1. System.getProperty("line.separator") 를 이용하기

  • 모든 개행이 지워지진 않음
// java 6 버전 이하
str.replaceAll(System.getProperty("line.separator"))
// java 7 버전 이상
str.replaceAll(System.lineSeparator())

2. "(\r\n|\r|\n|\n\r)" 이용

str.replaceAll("(\r\n|\r|\n|\n\r)", "")




JAVA HTTP Request, Response 메소드 내에서 생성하는 방법

첫번째

ServletWebRequest servletContainer = (ServletWebRequest)RequestContextHolder.getRequestAttributes();

HttpServletRequest request = servletContainer.getRequest();
HttpServletResponse response = servletContainer.getResponse();

두번째

HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getResponse();






참고사이트

Controller에서 HttpRequest Body 값은 왜 비워져 있을까? - ss.log

profile
tistory로 이전! https://sweet-rain-kim.tistory.com/

0개의 댓글