Obtener la carga útil de la solicitud de la solicitud POST en el servlet de Java

113

Tengo una biblioteca de JavaScript que envía una solicitud POST a mi servlet de Java, pero en el doPostmétodo, parece que no puedo obtener el contenido de la carga útil de la solicitud. En Chrome Developer Tools, todo el contenido está en la sección Request Payload en la pestaña de encabezados, y el contenido está allí, y sé que el método doPost está recibiendo el POST, pero simplemente aparece en blanco.

Para el HttpServletRequest objeto, ¿de qué manera puedo obtener los datos en la carga útil de la solicitud?

Haciendo request.getParameter()o request.getAttributes() ambos terminan sin datos

Fasih Awan
fuente
debe especificar qué parámetro, por ejemplo, si tiene una palabra clave en el cuerpo, use String keyword = request.getParameter ("palabra clave");
JustMe
Sería interesante ver el código JavaScript enviando la solicitud. Aparentemente, está componiendo los parámetros de solicitud de manera incorrecta.
BalusC
@Razh bueno, sí, lo sé, solo estaba especificando qué métodos estaba probando. BalusC Estoy usando la biblioteca resumable.js para manejar la carga de archivos divididos
Fasih Awan
4
Si no me equivoco, es importante que NO use request.getParameter () antes de leer el flujo de entrada, de lo contrario no habrá datos disponibles (ya leídos).
Jeach

Respuestas:

110

Respuesta simple:
use getReader () para leer el cuerpo de la solicitud

Más información:
Hay dos métodos para leer los datos en el cuerpo:

  1. getReader()devuelve un BufferedReader que le permitirá leer el cuerpo de la solicitud.

  2. getInputStream()devuelve un ServletInputStream si necesita leer datos binarios.

Nota de los documentos: "[Cualquier método] puede ser llamado para leer el cuerpo, no ambos".

davidfrancis
fuente
4
No hay problema, está un poco escondido ese
Davidfrancis
25
¡Esta publicación puede ser útil si acaba de usar esto en un filtro y luego descubrió que nada más puede leer el cuerpo nuevamente! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa
Esta es una respuesta realmente mala.
SargentoPooki
1
@SgtPooki no dude en agregar un razonamiento para ese comentario, ¡mi buen señor!
davidfrancis
@davidfrancis No estoy tratando de juzgarlo personalmente aquí, pero: no ha proporcionado ningún contexto ... no hay un enlace a la documentación, no hay ejemplo. Su respuesta a mi comentario parece haber requerido más esfuerzo que la respuesta en sí.
SgtPooki
68
String payloadRequest = getBody(request);

Usando este método

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;
}
Adrián Ayala Torres
fuente
6
Tenga en cuenta que request.getInputStream()no respeta la codificación de caracteres de solicitud como lo request.getReader()hace. Entonces, este ejemplo usa el juego de caracteres predeterminado del sistema.
Vadzim
9
new BufferedReader(new InputStreamReader(request.getInputStream()))podría simplificarse a request.getReader()que ya está almacenado en búfer y también conserva la codificación de solicitud.
Vadzim
1
Encontré esta solución útil ya que se lanzó una excepción: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestcuando llamé a getReader () como resultado de que el lector ya estaba abierto.
Benjamin Slabbert
52

Puede usar Buffer Reader desde la solicitud para leer

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

Flujos de Java 8

String body = request.getReader().lines()
    .reduce("", (accumulator, actual) -> accumulator + actual);
bbviana
fuente
Esto es interesante, ¡pero parece bastante ineficaz en términos de concatenación de cadenas! ¿De alguna manera esto se puede mejorar?
davidfrancis
11
String body = request.getReader (). Lines (). Collect (Collectors.joining ()); también puede funcionar. Collectors.joining usa un StringBuilder debajo del capó aparentemente.
Oliver Kohll
3
Creo que debería request.getReader (). Lines (). Collect (uniendo ("\ n")) para preservar las nuevas líneas.
Michael Böckling
En java 8, la transmisión se procesará en paralelo, por lo que es necesario agregar un método secuencial; de lo contrario, se fusionará la parte incorrecta de los datos: String body = request.getReader (). Lines (). Sequential (). Reduce (System.lineSeparator (), ( acumulador, actual) -> acumulador + actual)
Jatin Bodarya
2
Puede reemplazar (accumulator, actual) -> accumulator + actualcon String::concat.
shmosel
26

Con Apache Commons IO puede hacer esto en una línea.

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

Si el contenido del cuerpo es una cadena en Java 8, puede hacer:

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

Lloyd Rochester
fuente
5

Si puede enviar la carga útil en JSON, esta es la forma más conveniente de leer la carga de reproducción:

Clase de datos de ejemplo:

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

Carga útil de ejemplo (cuerpo de la solicitud):

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

Código para leer la carga útil en el servlet (requiere com.google.gson. *):

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

Eso es todo. Agradable, fácil y limpio. No olvide configurar el encabezado de tipo de contenido en application / json.

Harry Desarrollador
fuente
2

Usando Java 8 intente con recursos:

    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
fuente
1

Solo necesitas

request.getParameterMap ()

para obtener los parámetros POST y GET.

El método devuelve un Map<String,String[]> .

Puede leer los parámetros en el mapa por

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
fuente
2
Atención: los parámetros solo están disponibles si utiliza la codificación application/x-www-form-urlencoded; ya que multipart/form-data, aparentemente, necesita acceder a la parte del cuerpo request.getReader()y analizarla manualmente.
twonkeys