如何从java中的HttpServletRequest检索原始发布数据

B T*_*B T 55 java post servlets http

我正在尝试用Java获取发布数据.看起来它应该是最简单的事情之一吗?我的意思是,HttpServletRequest.getParameter必须做对吗?那么如何获得原始发布数据呢?

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

下面是我用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();
}
Run Code Online (Sandbox Code Playgroud)

以前我在这个方法结束时关闭了读者,但是当该方法在同一个请求上运行多次时会导致异常.不关闭它,不会发生异常,但该方法返回一个空字符串.

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

那么如何编写此方法以便始终返回正确的帖子数据?

Bal*_*usC 84

请求正文由HttpServletRequest#getInputStream()和提供#getReader().

InputStream body = request.getInputStream();
// ...
Run Code Online (Sandbox Code Playgroud)

请注意,您只能阅读一次.客户端不会多次重新发送它.调用getParameter()等等也会隐含地阅读它.你必须将身体存放在某个地方并自己处理.

  • 在第一次`getParameter()`调用时,`HttpServletRequest`将在内部使用`getInputStream()`来读取和解析请求体(它是来自网络连接的字节流)并将其存储在一个地图中,你可以通过` getParameterMap()`.在此之后,您不能再通过`getInputStream()`/`getReader()`读取请求体,因为它已被读取.如果您更多地阐明这种需求背后的功能需求,那么我们可能会建议您更好地实现它. (12认同)
  • 好吧,您可能想要创建一个`HttpServletRequestWrapper`,它在`ByteArrayInputStream`中保存请求体的副本. (8认同)
  • 以下是您正在寻找的请求Wrapper的示例:http://stackoverflow.com/questions/1046721/accessing-the-raw-body-of-a-put-or-post-request (6认同)
  • 所以你的答案是,没有*方法可以做我想做的事情?它不是关于客户端不止一次发送它.HttpServletRequest清楚地将内部数据存储在内部(因为您总是可以多次获得post参数).我很欣赏答案,我只是想完全理解你是说"不可能",还是只是在重新审视我已经发现的东西. (3认同)

dja*_*ham 7

我们遇到IE迫使我们以text/plain发布的情况,因此我们不得不使用getReader手动解析参数.servlet被用于长轮询,因此当延迟后执行AsyncContext :: dispatch时,它实际上是空转请求.

所以我只是在使用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\"}");
    }       
Run Code Online (Sandbox Code Playgroud)