Отримання корисного навантаження запиту від POST-запиту в сервлеті Java


113

У мене є бібліотека javascript, яка надсилає POST-запит на мій сервлет Java, але в цьому doPostметоді я не можу отримати вміст корисного навантаження запиту. У інструментах хромованого розробника весь вміст знаходиться у розділі Запит корисної навантаження на вкладці заголовків, і вміст є, і я знаю, що POST отримується методом doPost, але він просто порожній.

HttpServletRequest Яким чином для об'єкта я можу отримати дані в корисному завантаженні запиту?

Якщо у вас request.getParameter()або в request.getAttributes() обох випадках немає даних


вам потрібно вказати, який параметр, наприклад, якщо у вас є ключове слово в тілі, використовуйте ключове слово String = request.getParameter ("ключове слово");
щойно

Було б цікаво побачити код JavaScript, що надсилає запит. Очевидно, складання параметрів запиту неправильним чином.
BalusC

@Razh добре так я знаю, я просто вказував, які методи я намагався. BalusC Я використовую бібліотеку resumable.js для обробки розділених завантажень файлів
Фаших Аван,

4
Якщо я не помиляюсь, важливо, щоб ви не використовували request.getParameter () перед читанням з вхідного потоку, інакше дані не будуть доступні (вже прочитані).
Jeach

Відповіді:


110

Проста відповідь:
Використовуйте getReader () для читання тексту запиту

Докладніше:
Існує два способи зчитування даних в тілі:

  1. getReader()повертає BufferedReader, який дозволить вам прочитати тіло запиту.

  2. getInputStream()повертає ServletInputStream, якщо вам потрібно прочитати двійкові дані.

Зауважте в документах: "[Будь-який метод] може бути викликаний для зчитування тексту, а не обох."


4
Немає проблем, трохи приховано це одне
davidfrancis

25
Цей пост може бути корисним, якщо ви тільки що використали це у фільтрі, а потім виявили, що більше нічого не може прочитати тіло ще раз! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa

Це дійсно погана відповідь.
SgtPooki

1
@SgtPooki не соромтесь додати деякі міркування для цього коментаря, мій добрий пане!
davidfrancis

@davidfrancis Я тут не намагаюся судити вас особисто, але: ви не надали жодного контексту. Ні посилання на документацію, ні прикладу. Ваша відповідь на мій коментар вимагає більше зусиль, ніж сама відповідь.
SgtPooki

68
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;
}

6
Враховуйте те, що request.getInputStream()кодування символів не вимагає кодування запиту request.getReader(). Тож у цьому прикладі використовується стандартна системна схема.
Вадим

9
new BufferedReader(new InputStreamReader(request.getInputStream()))може бути спрощено до того, request.getReader()що вже є буферизованим, а також зберігає кодування запиту.
Вадим

1
Я вважаю це рішення корисним, оскільки виняток був кинутий: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestколи я зателефонував getReader (), в результаті читач уже відкритий.
Бенджамін Слабберт

52

Ви можете використовувати Buffer Reader від запиту до читання

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

40

Потоки Java 8

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

Це цікаво, але виглядає досить неефективно з точки зору об'єднання рядків! Будь-яким способом це можна покращити?
davidfrancis

11
String body = request.getReader (). Lines (). Collection (Collectors.joining ()); може також працювати. Collectors.joining, мабуть, використовує StringBuilder під кришкою.
Олівер Колл

3
Я думаю, що для запиту нових рядків слід запитувати.getReader (). Рядків (). Збирати (приєднуватися ("\ n")).
Майкл Бёклінг

У java 8 потік буде оброблятися паралельно, тому потрібно додати послідовний метод, інакше він об'єднає неправильну частину даних - String body = request.getReader (). Рядки (). Послідовний (), зменшення (System.lineSeparator (), ( акумулятор, фактичний) -> акумулятор + фактичний)
Jatin Bodarya

2
Ви можете замінити (accumulator, actual) -> accumulator + actualна String::concat.
shmosel


12

Якщо вміст тіла є рядком на Java 8, ви можете зробити:

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


5

Якщо вам вдається надіслати корисну навантаження в JSON, це найзручніший спосіб зчитувати завантаження:

Приклад класу даних:

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

Приклад корисного навантаження (орган запиту):

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

Код для зчитування корисного навантаження в сервлеті (потрібен com.google.gson. *):

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

Це все. Приємно, легко і чисто. Не забудьте встановити заголовок типу вмісту на додаток / json.


2

Використовуйте 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);
        }
    }

1

Вам потрібно лише

request.getParameterMap ()

для отримання POST та GET - Параметри.

Метод повертає a Map<String,String[]>.

Ви можете прочитати параметри на карті від

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);
    }
}

2
Остерігайтеся: параметри доступні лише у випадку використання кодування application/x-www-form-urlencoded; бо multipart/form-data, мабуть, вам потрібно отримати доступ до частини тіла через request.getReader()та проаналізувати її вручну.
twonkeys
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.