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.