如何从 Java 中的 HttpServletRequest 中检索原始帖子数据

2022-08-31 16:58:21

我正在尝试在Java中获取帖子数据。似乎它应该是最简单的事情之一?我的意思是,HttpServletRequest.getParameter必须做对吗?那么如何获取原始帖子数据呢?

我发现HttpServletRequest获取JSON POST数据,并使用Kdeveloper的代码从请求中提取post数据。它有效,但有一个问题:我只能获得一帖子数据。

以下是我从Kdeveloper的代码中创建的方法:

public static String getPostData(HttpServletRequest req) {
    StringBuilder sb = new StringBuilder();
    try {
        BufferedReader reader = req.getReader();
        reader.mark(10000);

        String line;
        do {
            line = reader.readLine();
            sb.append(line).append("\n");
        } while (line != null);
        reader.reset();
        // do NOT close the reader here, or you won't be able to get the post data twice
    } catch(IOException e) {
        logger.warn("getPostData couldn't.. get the post data", e);  // This has happened if the request's reader is closed    
    }

    return sb.toString();
}

以前,我在此方法结束时关闭了读取器,但是当该方法对同一请求运行多次时,这会导致异常。如果不关闭它,则不会发生异常,但该方法将返回一个空字符串。

老实说,应该只有一个公开的req.getPostData()方法 - 没有人认为这会有用吗?

那么我该如何编写此方法,使其始终返回正确的帖子数据呢?


答案 1

请求正文可通过 HttpServletRequest#getInputStream() 作为字节流使用:

InputStream body = request.getInputStream();
// ...

或者作为 HttpServletRequest#getReader() 的字符流:

Reader body = request.getReader();
// ...

请注意,您只能阅读一次。客户端不会多次重新发送相同的请求。调用等也会隐式读取它。如果你以后需要分解参数,你必须把身体存放在某个地方,然后自己处理。getParameter()


答案 2

我们遇到过这样的情况,IE强迫我们以文本/纯文本的形式发布,因此我们必须使用getReader手动解析参数。servlet 用于长轮询,因此当 AsyncContext::d ispatch 在延迟后执行时,它实际上是空手重新发布请求。

因此,我只是在请求中首次使用HttpServletRequest::setAttribute将其存储在请求中。getReader 方法清空缓冲区,其中 getParameter 也清空缓冲区,但自动存储参数。

    String input = null;

    // we have to store the string, which can only be read one time, because when the
    // servlet awakens an AsyncContext, it reposts the request and returns here empty handed
    if ((input = (String) request.getAttribute("com.xp.input")) == null) {
        StringBuilder buffer = new StringBuilder();
        BufferedReader reader = request.getReader();

        String line;
        while((line = reader.readLine()) != null){
            buffer.append(line);
        }
        // reqBytes = buffer.toString().getBytes();

        input = buffer.toString();
        request.setAttribute("com.xp.input", input);
    }

    if (input == null) {
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();
        out.print("{\"act\":\"fail\",\"msg\":\"invalid\"}");
    }