ChatGPT解决这个技术问题 Extra ChatGPT

Getting request payload from POST request in Java servlet

I have a javascript library that is sending a POST request to my Java servlet, but in the doPost method, I can't seem to get the contents of the request payload. In chrome Developer Tools, all the content is in the Request Payload section in the headers tab, and the content is there, and I know that the POST is being received by the doPost method, but it just comes up blank.

For the HttpServletRequest object, what way can I get the data in the request payload?

Doing request.getParameter() or request.getAttributes() both end up with no data

you need to specify which parameter e.g. if you have keyword in the body use String keyword = request.getParameter("keyword");
It'd be interesting to see the JavaScript code sending the request. It's apparently composing the request parameters in a wrong way.
@Razh well yes I know, I was just specifying which methods I was trying. BalusC I am using the resumable.js library to handle split file uploads
If I'm not mistaking, it's important that you do NOT use request.getParameter() prior to reading from the input stream otherwise no data will be available (already read).

d
davidfrancis

Simple answer: Use getReader() to read the body of the request

More info: There are two methods for reading the data in the body:

getReader() returns a BufferedReader that will allow you to read the body of the request. getInputStream() returns a ServletInputStream if you need to read binary data.

Note from the docs: "[Either method] may be called to read the body, not both."


No problems, it's a bit hidden that one
This post may be useful if you've just used this in a filter and then discovered nothing else can read the body again! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
@SgtPooki feel free to add some reasoning for that comment, my good sir!
@davidfrancis I'm not trying to judge you personally here, but: you have provided no context.. no link to documentation, no example. Your reply to my comment seems to have required more effort than the answer itself.
@SgtPooki Correct, as none of those things are needed. IMHO the name of the method needed is somewhat obscure, hence the method name is the answer to this question. Simple as that I thought. Feel free to submit a longer answer if you think it would be useful.
O
OneCricketeer
String payloadRequest = getBody(request);

Using this method

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;
}

Take into account that request.getInputStream() doesn't honor request character encoding as request.getReader() does. So this example uses default system charset.
new BufferedReader(new InputStreamReader(request.getInputStream())) could be simplified to just request.getReader() that is already buffered and also preserves request encoding.
I found this solution helpful as an exception was thrown: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this request when I called getReader() as a result of the reader already being open.
Thanks sir, this is a clean and concise solution!
why do you append empty string to the SB?
s
scriptfoo

You can use Buffer Reader from request to read

    // Read from request
    StringBuilder buffer = new StringBuilder();
    BufferedReader reader = request.getReader();
    String line;
    while ((line = reader.readLine()) != null) {
        buffer.append(line);
        buffer.append(System.lineSeparator());
    }
    String data = buffer.toString()

b
bbviana

Java 8 streams

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

This is interesting, but looks quite inefficient in terms of string concatenation! Any way this can be improved?
String body = request.getReader().lines().collect(Collectors.joining()); may also work. Collectors.joining uses a StringBuilder under the hood apparently.
I think it should request.getReader().lines().collect(joining("\n")) to preserve the newlines.
In java 8,stream will be processed parallely so need to add sequential method otherwise it will merge wrong portion of data - String body = request.getReader().lines().sequential().reduce(System.lineSeparator(), (accumulator, actual) -> accumulator + actual)
You can replace (accumulator, actual) -> accumulator + actual with String::concat.
D
Diji Adeyemo

With Apache Commons IO you can do this in one line.

IOUtils.toString(request.getReader())

t
twonkeys

If the contents of the body are a string in Java 8 you can do:

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


H
Harry Developer

If you are able to send the payload in JSON, this is a most convenient way to read the playload:

Example data class:

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

Example payload (request body):

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

Code to read payload in servlet (requires com.google.gson.*):

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

That's all. Nice, easy and clean. Don't forget to set the content-type header to application/json.


This worked in my case where I had to implement JWT authentication. I was sending JSON payload with username and password, then mapped that to my custom Auth Token class.
T
Timothy Heider

Using Java 8 try with resources:

    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);
        }
    }

K
Komal12

You only need

request.getParameterMap()

for getting the POST and GET - Parameters.

The Method returns a Map<String,String[]>.

You can read the parameters in the Map by

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);
    }
}

Beware: The parameters are only available if you use the encoding application/x-www-form-urlencoded; for multipart/form-data, you apparently need to access the body part through request.getReader() and parse it manually.