【问题标题】:Getting request payload from POST request in Java servlet从 Java servlet 中的 POST 请求获取请求有效负载
【发布时间】:2013-01-09 15:55:16
【问题描述】:

我有一个 javascript 库正在向我的 Java servlet 发送 POST 请求,但在 doPost 方法中,我似乎无法获取请求有效负载的内容。在 chrome 开发者工具中,所有内容都在 headers 选项卡的 Request Payload 部分,内容在那里,我知道 doPost 方法正在接收 POST,但它只是空白。

对于HttpServletRequest 对象,我可以通过什么方式获取请求负载中的数据?

正在做request.getParameter()request.getAttributes() 两者最终都没有数据

【问题讨论】:

  • 您需要指定哪个参数,例如如果正文中有关键字,请使用 String keyword = request.getParameter("keyword");
  • 看看发送请求的 JavaScript 代码会很有趣。它显然是以错误的方式组成请求参数。
  • @Razh 好吧,我知道,我只是在指定我正在尝试的方法。 BalusC 我正在使用 resumable.js 库来处理拆分文件上传
  • 如果我没记错的话,请务必不要在从输入流中读取之前使用 request.getParameter() ,否则将没有可用的数据(已经读取)。

标签: java http servlets post


【解决方案1】:

简单回答:
使用 getReader() 读取请求正文

更多信息:
读取body中的数据有两种方法:

  1. getReader() 返回一个BufferedReader,允许您读取请求的正文。

  2. getInputStream() 如果需要读取二进制数据,则返回ServletInputStream

来自文档的注释:“可以调用[任一方法] 来读取正文,而不是同时调用两者。”

【讨论】:

  • 没问题,那个有点隐蔽
  • 如果您刚刚在过滤器中使用了它,然后发现没有其他东西可以再次读取正文,那么这篇文章可能会很有用! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
  • @SgtPooki 随意为该评论添加一些推理,我的好先生!
  • @davidfrancis 我不是想在这里对您进行个人评判,但是:您没有提供任何上下文.. 没有文档链接,没有示例。您对我的评论的回复似乎比答案本身需要更多的努力。
  • @SgtPooki 正确,因为这些都不需要。恕我直言,所需方法的名称有些晦涩,因此方法名称就是这个问题的答案。和我想的一样简单。如果您认为有用,请随时提交更长的答案。
【解决方案2】:
String payloadRequest = getBody(request);

使用这个方法

public static String getBody(HttpServletRequest request) throws IOException {

    String body = null;
    StringBuilder stringBuilder = new StringBuilder();
    BufferedReader bufferedReader = null;

    try {
        InputStream inputStream = request.getInputStream();
        if (inputStream != null) {
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            char[] charBuffer = new char[128];
            int bytesRead = -1;
            while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                stringBuilder.append(charBuffer, 0, bytesRead);
            }
        } else {
            stringBuilder.append("");
        }
    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }

    body = stringBuilder.toString();
    return body;
}

【讨论】:

  • 考虑到request.getInputStream() 不像request.getReader() 那样接受请求字符编码。所以这个例子使用了默认的系统字符集。
  • new BufferedReader(new InputStreamReader(request.getInputStream())) 可以简化为 request.getReader(),它已经被缓冲并且还保留了请求编码。
  • 我发现这个解决方案很有帮助,因为引发了异常:javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this request 当我调用 getReader() 时因为阅读器已经打开。
  • 谢谢先生,这是一个简洁明了的解决方案!
  • 为什么要把空字符串附加到SB?
【解决方案3】:

您可以从请求中使用 Buffer Reader 来读取

    // Read from request
    StringBuilder buffer = new StringBuilder();
    BufferedReader reader = request.getReader();
    String line;
    while ((line = reader.readLine()) != null) {
        buffer.append(line);
        buffer.append(System.lineSeparator());
    }
    String data = buffer.toString()

【讨论】:

    【解决方案4】:

    Java 8 流

    String body = request.getReader().lines()
        .reduce("", (accumulator, actual) -> accumulator + actual);
    

    【讨论】:

    • 这很有趣,但在字符串连接方面看起来效率很低!有什么办法可以改进吗?
    • String body = request.getReader().lines().collect(Collectors.joining());也可以工作。 Collectors.joining 显然在后台使用了 StringBuilder。
    • 我认为应该 request.getReader().lines().collect(joining("\n")) 保留换行符。
    • 在 java 8 中,stream 将被并行处理,因此需要添加顺序方法,否则它将合并错误的数据部分 - String body = request.getReader().lines().sequential().reduce (System.lineSeparator(), (accumulator, actual) -> accumulator + actual)
    • 您可以将(accumulator, actual) -> accumulator + actual 替换为String::concat
    【解决方案5】:

    使用Apache Commons IO,您可以在一行中完成此操作。

    IOUtils.toString(request.getReader())
    

    【讨论】:

      【解决方案6】:

      如果正文的内容是 Java 8 中的字符串,您可以这样做:

      String body = request.getReader().lines().collect(Collectors.joining());

      【讨论】:

        【解决方案7】:

        如果您能够以 JSON 格式发送负载,这是读取负载的最便捷方式:

        示例数据类:

        public class Person {
            String firstName;
            String lastName;
            // Getters and setters ...
        }
        

        示例负载(请求正文):

        { "firstName" : "John", "lastName" : "Doe" }
        

        在 servlet 中读取有效负载的代码(需要 com.google.gson.*):

        Person person = new Gson().fromJson(request.getReader(), Person.class);
        

        就是这样。漂亮,简单,干净。不要忘记将 content-type 标头设置为 application/json。

        【讨论】:

        • 这适用于我必须实现 JWT 身份验证的情况。我正在发送带有用户名和密码的 JSON 有效负载,然后将其映射到我的自定义 Auth Token 类。
        【解决方案8】:

        使用 Java 8 尝试资源:

            StringBuilder stringBuilder = new StringBuilder();
            try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
                char[] charBuffer = new char[1024];
                int bytesRead;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            }
        

        【讨论】:

          【解决方案9】:

          你只需要

          request.getParameterMap()

          用于获取 POST 和 GET - 参数。

          该方法返回一个Map<String,String[]>

          您可以通过

          读取Map中的参数
          Map<String, String[]> map = request.getParameterMap();
          //Reading the Map
          //Works for GET && POST Method
          for(String paramName:map.keySet()) {
              String[] paramValues = map.get(paramName);
          
              //Get Values of Param Name
              for(String valueOfParam:paramValues) {
                  //Output the Values
                  System.out.println("Value of Param with Name "+paramName+": "+valueOfParam);
              }
          }
          

          【讨论】:

          • 注意:参数仅在使用编码application/x-www-form-urlencoded时可用;对于multipart/form-data,显然需要通过request.getReader() 访问正文部分并手动解析。
          猜你喜欢
          • 2013-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-28
          • 2015-09-04
          • 1970-01-01
          • 2018-04-23
          相关资源
          最近更新 更多