Ottenere il payload della richiesta dalla richiesta POST nel servlet Java


113

Ho una libreria javascript che invia una richiesta POST al mio servlet Java, ma nel doPostmetodo non riesco a ottenere il contenuto del payload della richiesta. Negli strumenti per sviluppatori di Chrome, tutto il contenuto si trova nella sezione Request Payload nella scheda delle intestazioni, e il contenuto è lì, e so che il POST viene ricevuto dal metodo doPost, ma risulta vuoto.

Per l' HttpServletRequest oggetto, in che modo posso ottenere i dati nel payload della richiesta?

Fare request.getParameter()o request.getAttributes() entrambi finiscono senza dati


è necessario specificare quale parametro, ad esempio, se si dispone di una parola chiave nel corpo, utilizzare String keyword = request.getParameter ("keyword");
— justMe

Sarebbe interessante vedere il codice JavaScript che invia la richiesta. Apparentemente sta componendo i parametri della richiesta in modo sbagliato.
— BalusC

@Razh, beh, sì, lo so, stavo solo specificando quali metodi stavo provando. BalusC Sto usando la libreria resumable.js per gestire i caricamenti di file divisi
— Fasih Awan

4
Se non sbaglio, è importante NON utilizzare request.getParameter () prima di leggere dal flusso di input altrimenti non saranno disponibili dati (già letti).
— Jeach

Risposte:


110

Risposta semplice:
usa getReader () per leggere il corpo della richiesta

Altre informazioni:
esistono due metodi per leggere i dati nel corpo:

  1. getReader()restituisce un BufferedReader che ti permetterà di leggere il corpo della richiesta.

  2. getInputStream()restituisce un ServletInputStream se è necessario leggere dati binari.

Nota dai documenti: "[Entrambi i metodi] possono essere chiamati per leggere il corpo, non entrambi."


4
Nessun problema, è un po 'nascosto quello
— davidfrancis

25
Questo post può essere utile se l'hai appena usato in un filtro e poi hai scoperto che nient'altro può leggere di nuovo il corpo! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
— JonnyRaa

Questa è davvero una brutta risposta.
— SgtPooki

1
@SgtPooki sentiti libero di aggiungere qualche motivazione per quel commento, mio ​​buon signore!
— davidfrancis

@davidfrancis Non sto cercando di giudicarti personalmente qui, ma: non hai fornito alcun contesto .. nessun link alla documentazione, nessun esempio. La tua risposta al mio commento sembra aver richiesto uno sforzo maggiore della risposta stessa.
— SgtPooki

68
String payloadRequest = getBody(request);

Usando questo metodo

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
Tieni presente che request.getInputStream()non rispetta la codifica dei caratteri richiesta come request.getReader()fa. Quindi questo esempio usa il set di caratteri di sistema predefinito.
— Vadzim

9
new BufferedReader(new InputStreamReader(request.getInputStream()))potrebbe essere semplificato solo request.getReader()che è già bufferizzato e preserva anche la codifica delle richieste.
— Vadzim

1
Ho trovato questa soluzione utile poiché è stata lanciata un'eccezione: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestquando ho chiamato getReader () perché il lettore era già aperto.
— Benjamin Slabbert,

52

È possibile utilizzare Buffer Reader dalla richiesta alla lettura

    // 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

Flussi Java 8

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

Questo è interessante, ma sembra piuttosto inefficiente in termini di concatenazione di stringhe! In qualche modo questo può essere migliorato?
— davidfrancis

11
Corpo della stringa = request.getReader (). Lines (). Collect (Collectors.joining ()); può anche funzionare. Collectors.joining utilizza uno StringBuilder sotto il cofano apparentemente.
— Oliver Kohll

3
Penso che dovrebbe request.getReader (). Lines (). Collect (join ("\ n")) per preservare le nuove righe.
— Michael Böckling

In java 8, lo stream verrà elaborato parallelamente, quindi è necessario aggiungere un metodo sequenziale altrimenti unirà una parte errata di dati - String body = request.getReader (). Lines (). Sequential (). Reduce (System.lineSeparator (), ( accumulatore, effettivo) -> accumulatore + effettivo)
— Jatin Bodarya

2
Puoi sostituire (accumulator, actual) -> accumulator + actualcon String::concat.
— shmosel


12

Se il contenuto del corpo è una stringa in Java 8 puoi fare:

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


5

Se sei in grado di inviare il payload in JSON, questo è il modo più conveniente per leggere il playload:

Classe di dati di esempio:

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

Payload di esempio (corpo della richiesta):

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

Codice per leggere il payload nel servlet (richiede com.google.gson. *):

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

È tutto. Bello, facile e pulito. Non dimenticare di impostare l'intestazione del tipo di contenuto su application / json.


2

Utilizzando Java 8 prova con le risorse:

    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

Hai solo bisogno

request.getParameterMap ()

per ottenere i parametri POST e GET.

Il metodo restituisce a Map<String,String[]>.

Puoi leggere i parametri nella mappa di

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
Attenzione: i parametri sono disponibili solo se si utilizza la codifica application/x-www-form-urlencoded; perché multipart/form-dataa quanto pare è necessario accedere alla parte del corpo request.getReader()e analizzarla manualmente.
— twonkeys
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.