web-dev-qa-db-fra.com

Comment récupérer les données de publication brutes de HttpServletRequest dans java

J'essaie d'obtenir les données de publication en Java. On dirait que cela devrait être l'une des choses les plus simples à faire correctement? Je veux dire, HttpServletRequest.getParameter doit le faire correctement? Alors, comment pouvez-vous obtenir les données de poste brutes?

J'ai trouvé HttpServletRequest get JSON POST données et a utilisé le code de Kdeveloper pour extraire les données de l'article d'une requête. Cela fonctionne, mais il y a un problème: je ne peux obtenir que cet article. données une fois .

Voici la méthode que j'ai créée à partir du code de 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();
}

Auparavant, j'avais fermé le lecteur à la fin de cette méthode, mais cela provoquait des exceptions lorsque la méthode s'exécutait plus d'une fois sur la même requête. Sans la fermer, aucune exception ne se produit, mais la méthode retourne une chaîne vide.

Honnêtement, il devrait y avoir juste une méthode req.getPostData () exposée - personne ne pensait que cela serait utile?

Alors, comment puis-je écrire cette méthode de telle sorte qu'elle renvoie toujours les données de publication correctes?

55
B T

Le corps de la demande est disponible par HttpServletRequest#getInputStream() et #getReader() .

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

Notez que vous ne pouvez le lire qu'une seule fois. Le client ne le renverra pas plusieurs fois. L'appel de getParameter() et ainsi de suite le lira aussi implicitement. Vous devez stocker le corps quelque part et vous soigner.

84
BalusC

Nous nous sommes trouvés dans une situation où IE nous a forcés à publier en tant que text/plain. Nous avons donc dû analyser manuellement les paramètres à l'aide de getReader. Le servlet était utilisé pour une longue interrogation, donc quand AsyncContext :: dispatch a été exécuté après un délai, il a été littéralement republié la demande les mains vides.

Donc, je viens de stocker la publication dans la demande lors de sa première apparition en utilisant HttpServletRequest :: setAttribute. La méthode getReader vide le tampon, où getParameter vide également le tampon mais stocke les paramètres automatiquement.

    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\"}");
    }       
7
djabraham