Abrufen der Anforderungsnutzdaten von der POST-Anforderung im Java-Servlet

113

Ich habe eine Javascript-Bibliothek, die eine POST-Anforderung an mein Java-Servlet sendet, aber in der doPostMethode kann ich den Inhalt der Anforderungsnutzdaten nicht abrufen. In den Chrome Developer Tools befindet sich der gesamte Inhalt im Abschnitt "Payload anfordern" auf der Registerkarte "Header" und der Inhalt ist dort. Ich weiß, dass der POST von der doPost-Methode empfangen wird, aber er wird nur leer angezeigt.

HttpServletRequest Wie kann ich für das Objekt die Daten in der Anforderungsnutzlast abrufen?

Tun request.getParameter()oder request.getAttributes() beide Ende ohne Daten auf

Fasih Awan
quelle
Sie müssen angeben, welcher Parameter verwendet werden soll, z. B. wenn Sie ein Schlüsselwort im Textkörper haben. Verwenden Sie String keyword = request.getParameter ("keyword").
JustMe
Es wäre interessant zu sehen, wie der JavaScript-Code die Anfrage sendet. Anscheinend werden die Anforderungsparameter falsch zusammengesetzt.
BalusC
@Razh gut ja ich weiß, ich habe nur angegeben, welche Methoden ich versucht habe. BalusC Ich benutze die Bibliothek resumable.js, um das Hochladen von geteilten Dateien zu handhaben
Fasih Awan
4
Wenn ich mich nicht irre, ist es wichtig, dass Sie request.getParameter () NICHT vor dem Lesen aus dem Eingabestream verwenden, da sonst keine Daten verfügbar sind (bereits gelesen).
Jeach

Antworten:

110

Einfache Antwort:
Verwenden Sie getReader (), um den Text der Anforderung zu lesen

Weitere Informationen:
Es gibt zwei Methoden zum Lesen der Daten im Körper:

  1. getReader()Gibt einen BufferedReader zurück , mit dem Sie den Hauptteil der Anforderung lesen können.

  2. getInputStream()Gibt einen ServletInputStream zurück, wenn Sie Binärdaten lesen müssen.

Anmerkung aus den Dokumenten: "[Jede Methode] kann aufgerufen werden, um den Textkörper zu lesen, nicht beide."

davidfrancis
quelle
4
Keine Probleme, es ist ein bisschen versteckt, dass man
Davidfrancis
25
Dieser Beitrag kann nützlich sein, wenn Sie ihn gerade in einem Filter verwendet haben und dann festgestellt haben, dass nichts anderes den Körper wieder lesen kann! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa
Das ist eine wirklich schlechte Antwort.
SgtPooki
1
@SgtPooki zögern Sie nicht, einige Gründe für diesen Kommentar hinzuzufügen, mein guter Herr!
Davidfrancis
@davidfrancis Ich versuche hier nicht, Sie persönlich zu beurteilen, aber: Sie haben keinen Kontext angegeben. Kein Link zur Dokumentation, kein Beispiel. Ihre Antwort auf meinen Kommentar scheint mehr Aufwand erfordert zu haben als die Antwort selbst.
SgtPooki
68
String payloadRequest = getBody(request);

Mit dieser Methode

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;
}
Adrian Ayala Torres
quelle
6
Berücksichtigen Sie, dass request.getInputStream()die Codierung von Anforderungszeichen nicht berücksichtigt request.getReader()wird. In diesem Beispiel wird also der Standard-Systemzeichensatz verwendet.
Vadzim
9
new BufferedReader(new InputStreamReader(request.getInputStream()))könnte vereinfacht werden, damit nur request.getReader()das bereits gepuffert ist und auch die Anforderungscodierung erhalten bleibt.
Vadzim
1
Ich fand diese Lösung hilfreich, da eine Ausnahme ausgelöst wurde: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestAls ich getReader () aufrief, weil der Reader bereits geöffnet war.
Benjamin Slabbert
52

Sie können den Buffer Reader von der Anforderung zum Lesen verwenden

    // 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()
Fizer Khan
quelle
40

Java 8-Streams

String body = request.getReader().lines()
    .reduce("", (accumulator, actual) -> accumulator + actual);
bbviana
quelle
Dies ist interessant, sieht aber in Bezug auf die Verkettung von Zeichenfolgen ziemlich ineffizient aus! Wie kann dies verbessert werden?
Davidfrancis
11
String body = request.getReader (). Lines (). Collect (Collectors.joining ()); kann auch funktionieren. Collectors.joining verwendet anscheinend einen StringBuilder unter der Haube.
Oliver Kohll
3
Ich denke, es sollte request.getReader (). Lines (). Collect (join ("\ n")) anfordern, um die Zeilenumbrüche beizubehalten.
Michael Böckling
In Java 8 wird der Stream parallel verarbeitet, daher muss eine sequentielle Methode hinzugefügt werden, da sonst ein falscher Teil der Daten zusammengeführt wird - String body = request.getReader (). Lines (). Sequential (). Reduce (System.lineSeparator (), () Akku, aktuell) -> Akku + aktuell)
Jatin Bodarya
2
Sie können ersetzen (accumulator, actual) -> accumulator + actualmit String::concat.
Shmosel
26

Mit Apache Commons IO können Sie dies in einer Zeile tun.

IOUtils.toString(request.getReader())
Diji Adeyemo
quelle
12

Wenn der Inhalt des Körpers in Java 8 eine Zeichenfolge ist, können Sie Folgendes tun:

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

Lloyd Rochester
quelle
5

Wenn Sie die Nutzdaten in JSON senden können, ist dies die bequemste Methode zum Lesen der Wiedergabe:

Beispieldatenklasse:

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

Beispielnutzlast (Anforderungshauptteil):

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

Code zum Lesen der Nutzdaten im Servlet (erfordert com.google.gson. *):

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

Das ist alles. Schön, einfach und sauber. Vergessen Sie nicht, den Header für den Inhaltstyp auf application / json zu setzen.

Harry Entwickler
quelle
2

Verwenden Sie Java 8 mit Ressourcen:

    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);
        }
    }
Timothy Heider
quelle
1

Du brauchst nur

request.getParameterMap ()

zum Abrufen der POST- und GET-Parameter.

Die Methode gibt a zurück Map<String,String[]>.

Sie können die Parameter in der Karte von lesen

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);
    }
}
Arol
quelle
2
Achtung: Die Parameter sind nur verfügbar, wenn Sie die Codierung verwenden application/x-www-form-urlencoded. für multipart/form-data, müssen Sie offensichtlich den Körperteil durch den Zugriff auf request.getReader()manuell und analysieren.
Schlüssel