Obtenir la charge utile de la requête à partir de la requête POST dans le servlet Java

113

J'ai une bibliothèque javascript qui envoie une requête POST à ​​mon servlet Java, mais dans la doPostméthode, je n'arrive pas à obtenir le contenu de la charge utile de la requête. Dans Chrome Developer Tools, tout le contenu se trouve dans la section Request Payload de l'onglet Headers, et le contenu y est, et je sais que le POST est reçu par la méthode doPost, mais il est juste vide.

Pour l' HttpServletRequest objet, comment puis-je obtenir les données dans la charge utile de la requête?

Faire request.getParameter()ou les request.getAttributes() deux se retrouvent sans données

Fasih Awan
la source
vous devez spécifier quel paramètre, par exemple si vous avez un mot-clé dans le corps, utilisez String keyword = request.getParameter ("mot-clé");
justMe
Il serait intéressant de voir le code JavaScript qui envoie la requête. Il compose apparemment les paramètres de la requête d'une manière incorrecte.
BalusC
@Razh eh bien oui je sais, je spécifiais juste quelles méthodes j'essayais. BalusC J'utilise la bibliothèque resumable.js pour gérer les téléchargements de fichiers fractionnés
Fasih Awan
4
Si je ne me trompe pas, il est important que vous n'utilisiez PAS request.getParameter () avant de lire à partir du flux d'entrée, sinon aucune donnée ne sera disponible (déjà lue).
Jeach

Réponses:

110

Réponse simple:
utilisez getReader () pour lire le corps de la requête

Plus d'infos:
Il existe deux méthodes pour lire les données dans le corps:

  1. getReader()renvoie un BufferedReader qui vous permettra de lire le corps de la requête.

  2. getInputStream()renvoie un ServletInputStream si vous avez besoin de lire des données binaires.

Note de la documentation: "[L'une ou l'autre méthode] peut être appelée pour lire le corps, pas les deux."

Davidfrancis
la source
4
Pas de problème, c'est un peu caché celui-là
davidfrancis
25
Cet article peut être utile si vous venez de l'utiliser dans un filtre et que vous avez découvert que rien d'autre ne peut lire à nouveau le corps! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa
C'est une très mauvaise réponse.
SgtPooki
1
@SgtPooki, n'hésitez pas à ajouter un raisonnement à ce commentaire, mon bon monsieur!
davidfrancis
@davidfrancis Je n'essaie pas de vous juger personnellement ici, mais: vous n'avez fourni aucun contexte .. aucun lien vers la documentation, aucun exemple. Votre réponse à mon commentaire semble avoir demandé plus d'efforts que la réponse elle-même.
SgtPooki
68
String payloadRequest = getBody(request);

En utilisant cette méthode

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
la source
6
Tenez compte du fait que request.getInputStream()cela n'honore pas le codage des caractères de la demande comme le request.getReader()fait. Donc, cet exemple utilise le jeu de caractères système par défaut.
Vadzim
9
new BufferedReader(new InputStreamReader(request.getInputStream()))pourrait être simplifié à ce request.getReader()qui est déjà mis en mémoire tampon et préserve également le codage des demandes.
Vadzim
1
J'ai trouvé cette solution utile car une exception a été levée: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestlorsque j'ai appelé getReader () car le lecteur était déjà ouvert.
Benjamin Slabbert
52

Vous pouvez utiliser Buffer Reader à partir de la demande de lecture

    // 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
la source
40

Flux Java 8

String body = request.getReader().lines()
    .reduce("", (accumulator, actual) -> accumulator + actual);
bbviana
la source
Ceci est intéressant, mais semble assez inefficace en termes de concaténation de chaînes! Est-ce que cela peut être amélioré?
davidfrancis
11
String body = request.getReader (). Lines (). Collect (Collectors.joining ()); peut également fonctionner. Collectors.joining utilise apparemment un StringBuilder sous le capot.
Oliver Kohll
3
Je pense qu'il devrait request.getReader (). Lines (). Collect (join ("\ n")) pour conserver les nouvelles lignes.
Michael Böckling
Dans java 8, le flux sera traité en parallèle, il faut donc ajouter une méthode séquentielle sinon il fusionnera une mauvaise partie des données - String body = request.getReader (). Lines (). Sequential (). Reduction (System.lineSeparator (), ( accumulateur, réel) -> accumulateur + réel)
Jatin Bodarya
2
Vous pouvez remplacer (accumulator, actual) -> accumulator + actualpar String::concat.
shmosel
12

Si le contenu du corps est une chaîne en Java 8, vous pouvez faire:

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

Lloyd Rochester
la source
5

Si vous êtes en mesure d'envoyer la charge utile en JSON, c'est le moyen le plus pratique de lire la charge de lecture:

Exemple de classe de données:

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

Exemple de charge utile (corps de la requête):

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

Code pour lire la charge utile dans le servlet (nécessite com.google.gson. *):

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

C'est tout. Nice, facile et propre. N'oubliez pas de définir l'en-tête de type de contenu sur application / json.

Développeur Harry
la source
2

Utilisation de Java 8 essayez avec des ressources:

    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
la source
1

Tu a juste besoins

request.getParameterMap ()

pour obtenir les paramètres POST et GET.

La méthode renvoie un Map<String,String[]>.

Vous pouvez lire les paramètres de la carte en

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
la source
2
Attention: les paramètres ne sont disponibles que si vous utilisez l'encodage application/x-www-form-urlencoded; car multipart/form-data, vous devez apparemment accéder à la partie du corps request.getReader()et l'analyser manuellement.
twonkeys