从HttpServletRequest获取POST请求正文


113

我试图从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上附加任何内容。

Answers:


190

在Java 8中,您可以用一种更简单,更干净的方式来做到这一点:

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

7
我更喜欢这种解决方案,因为它是纯Java,没有任何第三方依赖。
lu_ko

49
尽管请记住,我们无法像getReader已经被调用那样再次读取请求正文。
Nikhil Sahu

1
我们如何再次将新格式化的HTTP POST数据放回请求中?
Pra_A

1
我已经尝试过此解决方案,但它引入了一个非常严重的问题,我使用此代码将请求信息记录在一次afterPerRequest过滤器中,当我使用它时,我所有post方法中的所有@modelAttribute绑定在对象。我不建议使用这种方法。
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'Aug

我得到了java.lang.IllegalStateException:此请求已调用getReader()
Pra_A

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 "";
}


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

我以这种方式解决了这种情况。我创建了一个util方法,该方法使用能够接收Reader的ObjectMapper的readValue方法返回从请求主体提取的对象。

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?
Ferry Kranenburg

我敢打赌这是来自Liferay,特定于Liferay的API
mvmn
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.