Как получить необработанные данные поста из HttpServletRequest в Java - PullRequest
55 голосов
/ 17 февраля 2011

Я пытаюсь получить данные поста в 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();
}

Ранее я имелзакрыл читателя в конце этого метода, но это вызвало исключения, когда метод выполнялся более одного раза по одному и тому же запросу.Без его закрытия не происходит никаких исключений, но метод возвращает пустую строку.

Честно говоря, должен быть только открытый метод req.getPostData () - никто не думал, что это будет полезно?

Так, как я могу написать этот метод так, чтобы он всегда возвращал правильные данные сообщения?

Ответы [ 2 ]

84 голосов
/ 17 февраля 2011

Тело запроса доступно для HttpServletRequest#getInputStream() и #getReader().

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

Обратите внимание, что вы можете прочитать его только один раз.Клиент не собирается отправлять его несколько раз.Вызов getParameter() и так далее неявно также прочитает его.Вы должны где-то хранить тело и обрабатывать себя.

7 голосов
/ 06 июня 2013

У нас была ситуация, когда IE заставлял нас публиковать текстовые / обычные тексты, поэтому нам пришлось вручную анализировать параметры с помощью getReader. Сервлет использовался для длинного опроса, поэтому, когда 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\"}");
    }       
...