简体   繁体   English

如何在java中从HttpServletRequest检索原始帖子数据

[英]How to retrieve raw post data from HttpServletRequest in java

I'm trying to get the post data in Java.我正在尝试用 Java 获取帖子数据。 Seems like it should be one of the simplest things to do right?似乎这应该是最简单的事情之一吧? I mean, HttpServletRequest.getParameter has to do it right?我的意思是, HttpServletRequest.getParameter 必须这样做对吗? So how can you get the raw post data?那么如何获得原始的帖子数据呢?

I found HttpServletRequest get JSON POST data and used Kdeveloper's code to pull the post data from a request.我发现HttpServletRequest 获取 JSON POST 数据并使用 Kdeveloper 的代码从请求中提取发布数据。 It works, but theres a catch: I can only get that post data once .它有效,但有一个问题:我只能获得一次发布数据。

Heres the method I made from Kdeveloper's code:这是我从 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();
}

Previously I had closed the reader at the end of this method, but that caused exceptions when the method ran more than once on the same request.以前我在此方法的末尾关闭了读取器,但是当该方法在同一请求上运行多次时会导致异常。 Without closing it, no exceptions happen, but the method returns an empty string.不关闭它,不会发生异常,但该方法返回一个空字符串。

Honestly, there should just be an exposed req.getPostData() method - did no one think that would be useful?老实说,应该只有一个公开的 req.getPostData() 方法 - 没有人认为这会有用吗?

So how can I write this method such that it always returns the correct post data?那么我该如何编写这个方法,让它始终返回正确的发布数据呢?

The request body is available as byte stream by HttpServletRequest#getInputStream() :请求正文可通过HttpServletRequest#getInputStream()作为字节流使用:

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

Or as character stream by HttpServletRequest#getReader() :或者作为HttpServletRequest#getReader()字符流:

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

Note that you can read it only once.请注意,您只能阅读一次。 The client ain't going to resend the same request multiple times.客户端不会多次重新发送相同的请求。 Calling getParameter() and so on will implicitly also read it.调用getParameter()等也会隐式读取它。 If you need to break down parameters later on, you've got to store the body somewhere and process yourself.如果您稍后需要分解参数,则必须将主体存储在某处并自行处理。

We had a situation where IE forced us to post as text/plain, so we had to manually parse the parameters using getReader.我们遇到过 IE 强制我们以 text/plain 形式发布的情况,因此我们不得不使用 getReader 手动解析参数。 The servlet was being used for long polling, so when AsyncContext::dispatch was executed after a delay, it was literally reposting the request empty handed. servlet 被用于长轮询,所以当 AsyncContext::dispatch 在延迟后执行时,它实际上是空手重新发布请求。

So I just stored the post in the request when it first appeared by using HttpServletRequest::setAttribute.所以我只是在使用 HttpServletRequest::setAttribute 首次出现时将帖子存储在请求中。 The getReader method empties the buffer, where getParameter empties the buffer too but stores the parameters automagically. 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\"}");
    }       

This worked for me: (notice that java 8 is required)这对我有用:(请注意需要 java 8)

String requestData = request.getReader().lines().collect(Collectors.joining());
UserJsonParser u = gson.fromJson(requestData, UserJsonParser.class);

UserJsonParse is a class that shows gson how to parse the json formant. UserJsonParse 是一个展示 gson 如何解析 json 共振峰的类。

class is like that:班级是这样的:

public class UserJsonParser {

    private String username;
    private String name;
    private String lastname;
    private String mail;
    private String pass1;
//then put setters and getters
}

the json string that is parsed is like that:解析的 json 字符串是这样的:

$jsonData: {    "username": "testuser",    "pass1": "clave1234" }

The rest of values (mail, lastname, name) are set to null其余值(邮件、姓氏、姓名)设置为空

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM