Mendapatkan payload permintaan dari permintaan POST di servlet Java

113

Saya memiliki pustaka javascript yang mengirimkan permintaan POST ke servlet Java saya, tetapi dalam doPostmetode ini, saya tidak bisa mendapatkan konten dari muatan permintaan. Di Chrome Developer Tools, semua konten ada di bagian Minta Payload di tab header, dan kontennya ada di sana, dan saya tahu bahwa POST sedang diterima oleh metode doPost, tetapi hasilnya kosong.

Untuk HttpServletRequest objek, dengan cara apa saya bisa mendapatkan data di payload permintaan?

Melakukan request.getParameter()atau request.getAttributes() keduanya berakhir tanpa data

Fasih Awan
sumber
Anda perlu menentukan parameter mana misalnya jika Anda memiliki kata kunci dalam tubuh gunakan String keyword = request.getParameter ("keyword");
justMe
Menarik untuk melihat kode JavaScript yang mengirimkan permintaan tersebut. Tampaknya menyusun parameter permintaan dengan cara yang salah.
BalusC
@Razh baik ya saya tahu, saya baru saja menentukan metode mana yang saya coba. BalusC Saya menggunakan perpustakaan resumable.js untuk menangani unggahan file yang terbagi
Fasih Awan
4
Jika saya tidak salah, penting bagi Anda untuk JANGAN menggunakan request.getParameter () sebelum membaca dari aliran input jika tidak, data tidak akan tersedia (sudah dibaca).
Jeach

Jawaban:

110

Jawaban sederhana:
Gunakan getReader () untuk membaca isi permintaan

Info selengkapnya:
Ada dua metode untuk membaca data di body:

  1. getReader()mengembalikan BufferedReader yang memungkinkan Anda membaca isi permintaan.

  2. getInputStream()mengembalikan ServletInputStream jika Anda perlu membaca data biner.

Catatan dari dokumen: "[Metode mana pun] dapat dipanggil untuk membaca isi, bukan keduanya."

davidfrancis
sumber
4
Tidak masalah, itu agak tersembunyi
davidfrancis
25
Posting ini mungkin berguna jika Anda baru saja menggunakan ini di filter dan kemudian menemukan tidak ada lagi yang dapat membaca isi lagi! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa
Ini jawaban yang sangat buruk.
SgtPooki
1
@SgtPooki jangan ragu untuk menambahkan beberapa alasan untuk komentar itu, Pak!
davidfrancis
@davidfrancis Saya tidak mencoba menilai Anda secara pribadi di sini, tetapi: Anda tidak memberikan konteks .. tidak ada tautan ke dokumentasi, tidak ada contoh. Balasan Anda untuk komentar saya tampaknya membutuhkan lebih banyak usaha daripada jawaban itu sendiri.
SgtPooki
68
String payloadRequest = getBody(request);

Menggunakan metode ini

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
sumber
6
Mempertimbangkan bahwa request.getInputStream()tidak menghormati pengkodean karakter permintaan seperti request.getReader()halnya. Jadi contoh ini menggunakan charset sistem default.
Vadzim
9
new BufferedReader(new InputStreamReader(request.getInputStream()))dapat disederhanakan menjadi hanya request.getReader()yang sudah di-buffer dan juga mempertahankan encoding permintaan.
Vadzim
1
Saya menemukan solusi ini bermanfaat karena pengecualian dilemparkan: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestketika saya memanggil getReader () sebagai akibat dari pembaca sudah terbuka.
Benjamin Slabbert
52

Anda dapat menggunakan Buffer Reader dari permintaan untuk membaca

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

Aliran Java 8

String body = request.getReader().lines()
    .reduce("", (accumulator, actual) -> accumulator + actual);
bbviana.dll
sumber
Ini menarik, tetapi terlihat sangat tidak efisien dalam hal penggabungan string! Adakah cara agar hal ini dapat ditingkatkan?
davidfrancis
11
String body = request.getReader (). Lines (). Collect (Collectors.joining ()); mungkin juga bekerja. Collectors.joining menggunakan StringBuilder di bawah tenda.
Oliver Kohll
3
Saya pikir itu harus request.getReader (). Lines (). Collect (bergabung ("\ n")) untuk mempertahankan baris baru.
Michael Böckling
Di java 8, aliran akan diproses secara paralel sehingga perlu menambahkan metode sekuensial jika tidak maka akan menggabungkan bagian data yang salah - String body = request.getReader (). Lines (). Sequential (). Reduce (System.lineSeparator (), ( akumulator, aktual) -> akumulator + aktual)
Jatin Bodarya
2
Anda bisa mengganti (accumulator, actual) -> accumulator + actualdengan String::concat.
shmosel
26

Dengan Apache Commons IO, Anda dapat melakukan ini dalam satu baris.

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

Jika isi body berupa string di Java 8 Anda bisa melakukan:

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

Lloyd Rochester
sumber
5

Jika Anda dapat mengirim payload dalam JSON, ini adalah cara paling nyaman untuk membaca playload:

Contoh kelas data:

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

Contoh payload (isi permintaan):

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

Kode untuk membaca payload di servlet (membutuhkan com.google.gson. *):

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

Itu saja. Bagus, mudah dan bersih. Jangan lupa untuk mengatur header tipe konten ke application / json.

Pengembang Harry
sumber
2

Menggunakan Java 8 coba dengan sumber daya:

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

Anda hanya butuh

request.getParameterMap ()

untuk mendapatkan POST dan GET - Parameter.

Metode mengembalikan a Map<String,String[]>.

Anda dapat membaca parameter di Peta dengan

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
sumber
2
Hati-hati: Parameter hanya tersedia jika Anda menggunakan pengkodean application/x-www-form-urlencoded; Sebab multipart/form-data, Anda tampaknya perlu mengakses bagian tubuh melalui request.getReader()dan menguraikannya secara manual.
twonkeys