HttpServletRequest에서 POST 요청 본문 가져 오기


115

HttpServletRequest 개체에서 전체 본문을 가져 오려고합니다.

내가 따르는 코드는 다음과 같습니다.

if ( request.getMethod().equals("POST") )
{
    StringBuffer sb = new StringBuffer();
    BufferedReader bufferedReader = null;
    String content = "";

    try {
        //InputStream inputStream = request.getInputStream();
        //inputStream.available();
        //if (inputStream != null) {
        bufferedReader =  request.getReader() ; //new BufferedReader(new InputStreamReader(inputStream));
        char[] charBuffer = new char[128];
        int bytesRead;
        while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
            sb.append(charBuffer, 0, bytesRead);
        }
        //} else {
        //        sb.append("");
        //}

    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }

    test = sb.toString();
}

다음과 같이 curl 및 wget으로 기능을 테스트하고 있습니다.

curl --header "MD5: abcd" -F "fileupload=@filename.txt http://localhost:8080/abcd.html"

wget --header="MD5: abcd" --post-data='{"imei":"351553012623446","hni":"310150","wdp":false}' http://localhost:8080/abcd.html"

그러나 while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 )아무것도 반환하지 않으므로 StringBuffer에 아무것도 추가되지 않습니다.

답변:


192

Java 8에서는 더 간단하고 깔끔한 방법으로 수행 할 수 있습니다.

if ("POST".equalsIgnoreCase(request.getMethod())) 
{
   test = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}

8
타사 종속성이없는 순수 Java이기 때문에이 솔루션을 선호합니다.
— lu_ko 2013-08-31

49
getReader이미 호출되었으므로 요청 본문을 다시 읽을 수는 없습니다 .
— Nikhil Sahu

1
새로 포맷 된 HTTP POST 데이터를 어떻게 다시 요청으로 되돌릴 수 있습니까?
— Pra_A

1
이 솔루션을 시도했지만 매우 심각한 전제 조건을 도입했습니다.이 코드를 사용하여 oncePerRequest 필터 내부에 요청 정보를 기록하고 사용했을 때 모든 게시물 메서드의 모든 @modelAttribute 바인딩이 모든 필드에 null을 부여했습니다. object.이 접근 방식을 사용하지 않는 것이 좋습니다.
— Mohammed Fathi

독자를 닫아야합니까?
— aristo_sh

46

commons-io를 사용하는 쉬운 방법.

IOUtils.toString(request.getReader());

https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/IOUtils.html


독자의 출력이 어떻게 보이는지 (즉, 키 표시 여부)에 대한 예를 제시해 주시면 도움이 될 것입니다.
— ArthurG

이것은 나를 위해 일했습니다. 나는이 솔루션은 또한 일반적인 시나리오를 피할 것을 확인 할 수있는 뚜렷한 이유없이 bufferedreader.readLine () "중지"
— NAREN

안녕하세요 @DavidDomingo, 100 % 작동합니다. 위의 응답에서 동일한 댓글을 작성하고 있음을 읽을 수 있습니다 (또한 작동 함). 코드의 어딘가 (아마도 필터링) 또는 Spring에 의해 누군가 때문에 getReader () 메서드가 전에 호출되지 않았는지 확인하십시오. 두 번 이상 호출하면 첫 번째 페이로드 만 반환하기 때문입니다.
— Dani

안녕하세요 @Dani, 그것이 작동하지 않는 이유입니다. 독자가 비어 있습니다. 나는 RestController가 당신이 어떤 끝점에서 그것을 할 수 있기 전에 그것을 읽는다고 생각합니다. 본문을 얻는 가장 쉬운 방법은 HttpEntity를 사용하는 것입니다.
— David Domingo

31

코드가 상당히 시끄럽다는 점에 유의하십시오. 나는 스레드가 오래되었다는 것을 알고 있지만 어쨌든 많은 사람들이 그것을 읽을 것입니다. 다음과 같이 guava 라이브러리를 사용하여 동일한 작업을 수행 할 수 있습니다.

    if ("POST".equalsIgnoreCase(request.getMethod())) {
        test = CharStreams.toString(request.getReader());
    }

3
아마도 고려하십시오if(RequestMethod.POST.name().equalsIgnoreCase(...)) { ... }
— Madbreaks

java.lang.IllegalStateException이 발생합니다. getReader ()가이 요청에 대해 이미 호출되었습니다
— Pra_A dec

18

원하는 것이 POST 요청 본문뿐이라면 다음과 같은 방법을 사용할 수 있습니다.

static String extractPostRequestBody(HttpServletRequest request) throws IOException {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

크레딧 : https://stackoverflow.com/a/5445161/1389219


1
request.getInputStream()요청 문자 인코딩 을 따르지 않는 것을 고려하십시오 request.getReader(). 링크는 +1.
— Vadzim 2014

PUT 방법과 동등한 것은 무엇입니까?
— devanathan

10

이것은 GET과 POST 모두에서 작동합니다.

@Context
private HttpServletRequest httpRequest;


private void printRequest(HttpServletRequest httpRequest) {
    System.out.println(" \n\n Headers");

    Enumeration headerNames = httpRequest.getHeaderNames();
    while(headerNames.hasMoreElements()) {
        String headerName = (String)headerNames.nextElement();
        System.out.println(headerName + " = " + httpRequest.getHeader(headerName));
    }

    System.out.println("\n\nParameters");

    Enumeration params = httpRequest.getParameterNames();
    while(params.hasMoreElements()){
        String paramName = (String)params.nextElement();
        System.out.println(paramName + " = " + httpRequest.getParameter(paramName));
    }

    System.out.println("\n\n Row data");
    System.out.println(extractPostRequestBody(httpRequest));
}

static String extractPostRequestBody(HttpServletRequest request) {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = null;
        try {
            s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

9

요청 본문이 비어있는 경우 단순히 미리 사용되었음을 의미합니다. 예를 들어,에 의해 request.getParameter(), getParameterValues()또는 getParameterMap()전화. 코드에서 이러한 호출을 수행하는 줄을 제거하십시오.


curl예를 들어 파일 업로드가 아닌 경우에만 작동합니다 .
— Dave Newton

1
나는 이것을 시도했다. 하지만 여전히 POST 본문을 얻지 못하고 있습니다. 뭔가 빠졌 나봐요. 추가하기 위해 : 저는 개발을 위해 Tapestry를 사용하고 있습니다.
— patel bhavin 2011

3

이것은 모든 HTTP 메소드에서 작동합니다.

public class HttpRequestWrapper extends HttpServletRequestWrapper {
    private final String body;

    public HttpRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = IOUtils.toString(request.getReader());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getBody().getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

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

            @Override
            public void setReadListener(ReadListener listener) {
            }

        };
        return servletInputStream;
    }

    public String getBody() {
        return this.body;
    }
}

0

나는 이런 식으로 그 상황을 해결했다. Reader를받을 수있는 ObjectMapper의 readValue 메서드를 사용하여 요청 본문에서 추출한 개체를 반환하는 util 메서드를 만들었습니다.

public static <T> T getBody(ResourceRequest request, Class<T> class) {
    T objectFromBody = null;
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpServletRequest httpServletRequest = PortalUtil.getHttpServletRequest(request);
        objectFromBody = objectMapper.readValue(httpServletRequest.getReader(), class);
    } catch (IOException ex) {
        log.error("Error message", ex);
    }
    return objectFromBody;
}

1
PortalUtil은 무엇입니까?
— 페리 Kranenburg

나는 이것이 Liferay, Liferay 특정 API
— 가져온 것이라고 확신
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.