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

时间:2011-02-17 00:08:11

标签: java http servlets post

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

我找到HttpServletRequest get JSON POST data并使用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();
}

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

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

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

3 个答案:

答案 0 :(得分:84)

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

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

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

答案 1 :(得分: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\"}");
    }       

答案 2 :(得分:1)

这对我有用:(请注意,需要Java 8)

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

UserJsonParse是一个类,向gson显示如何解析json共振峰。

类是这样的:

public class UserJsonParser {

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

被解析的json字符串是这样的:

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

其余值(邮件,姓氏,姓名)设置为空