从HttpServletRequest获取POST请求正文

pat*_*vin 90 java post servlets

我试图从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();
}
Run Code Online (Sandbox Code Playgroud)

我正在使用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"
Run Code Online (Sandbox Code Playgroud)

但是while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 )它没有返回任何内容,因此我没有在StringBuffer上附加任何内容.

abh*_*bhi 160

在Java 8中,您可以以更简单,更干净的方式执行此操作:

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

  • 但请记住,我们无法再次读取请求体,因为已经调用了`getReader`. (30认同)
  • 我更喜欢这个解决方案,因为它是纯Java而没有任何第三方依赖. (7认同)
  • @MohammedFathi,您必须创建一个 WebMvcConfigurer 并添加一个拦截器,您可以在其中 HttpServletRequest requestCache = new ContentCachingRequestWrapper(request); 然后将 requestCache 对象用于您的日志 (4认同)
  • 我们如何才能将新格式化的 HTTP POST 数据重新设置回请求中? (2认同)
  • 我已经尝试过这个解决方案,但它引入了一个非常严重的问题,我使用此代码在 OncePerRequest 过滤器中记录请求信息,当我使用它时,我所有 post 方法中的所有 @modelAttribute 绑定在 an 的所有字段中都给出了 null object 。我不建议使用这种方法。 (2认同)

Dan*_*ani 35

简单的方式与commons-io.

IOUtils.toString(request.getReader());
Run Code Online (Sandbox Code Playgroud)

https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/IOUtils.html

  • @DavidDomingo,您好,它 100% 有效,我可以看到您在上面的回复中发表了相同的评论(也有效)。检查代码中的某个位置(可能会过滤),或者可能是因为 Spring 的某个人,之前没有调用 getReader() 方法,因为如果你调用它两次或更多次,它只返回第一个有效负载。 (2认同)

afx*_*afx 27

请注意,您的代码非常嘈杂.我知道线程已经过时了,但很多人都会读它.您可以使用guava库执行相同的操作:

    if ("POST".equalsIgnoreCase(request.getMethod())) {
        test = CharStreams.toString(request.getReader());
    }
Run Code Online (Sandbox Code Playgroud)

  • 也许考虑`if(RequestMethod.POST.name().equalsIgnoreCase(...)){...}` (3认同)
  • 我收到 java.lang.IllegalStateException: getReader() 已为此请求调用 (2认同)

veg*_*4me 17

如果你想要的只是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 "";
}
Run Code Online (Sandbox Code Playgroud)

感谢:https://stackoverflow.com/a/5445161/1389219


Bal*_*usC 8

如果请求体是空的,那么它只是意味着它已经被预先消耗了.例如,通过一个request.getParameter(),getParameterValues()getParameterMap()呼叫.只需从代码中删除执行这些调用的行.


Bru*_*uno 7

这适用于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 "";
}
Run Code Online (Sandbox Code Playgroud)


小智 6

我能想到的最简单的方法:

request.getReader().lines().reduce("",String::concat)
Run Code Online (Sandbox Code Playgroud)
  • 但是,这将是一个您必须解析的长字符串。如果您发送用户名tim和密码12345。上面代码的输出如下所示:
{    "username":"tim",    "password": "12345"}
Run Code Online (Sandbox Code Playgroud)

请注意

  • 请注意,使用 reduce() 方法,我们正在执行可变缩减,它会进行大量字符串复制,并且运行时间为 O(N^2),其中 N 是字符数。如果您需要更高性能的结果,请查看可变归约文档。


小智 5

这适用于所有 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;
    }
}
Run Code Online (Sandbox Code Playgroud)