Dapatkan badan permintaan POST dari HttpServletRequest


115

Saya mencoba untuk mendapatkan seluruh isi dari objek HttpServletRequest.

Kode yang saya ikuti terlihat seperti ini:

if ( request.getMethod().equals("POST") )
{
    StringBuffer sb = new StringBuffer();
    BufferedReader bufferedReader = null;
    String content = "";

    try {
        //InputStream inputStream = request.getInputStream();
        //inputStream.available();
        //if (inputStream != null) {
        bufferedReader =  request.getReader() ; //new BufferedReader(new InputStreamReader(inputStream));
        char[] charBuffer = new char[128];
        int bytesRead;
        while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
            sb.append(charBuffer, 0, bytesRead);
        }
        //} else {
        //        sb.append("");
        //}

    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }

    test = sb.toString();
}

dan saya menguji fungsionalitas dengan curl dan wget sebagai berikut:

curl --header "MD5: abcd" -F "fileupload=@filename.txt http://localhost:8080/abcd.html"

wget --header="MD5: abcd" --post-data='{"imei":"351553012623446","hni":"310150","wdp":false}' http://localhost:8080/abcd.html"

Tetapi while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 )tidak mengembalikan apa pun, jadi saya tidak mendapatkan apa pun yang ditambahkan di StringBuffer.

Jawaban:


192

Di Java 8, Anda dapat melakukannya dengan cara yang lebih sederhana dan bersih:

if ("POST".equalsIgnoreCase(request.getMethod())) 
{
   test = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}

8
Saya lebih suka solusi ini karena ini adalah Java murni tanpa ketergantungan pihak ke-3.
lu_ko

49
Meskipun perlu diingat bahwa kami tidak dapat membaca badan permintaan lagi karena getReadertelah dipanggil.
Nikhil Sahu

1
Bagaimana kita bisa mengatur kembali data HTTP POST yang baru diformat kembali ke dalam permintaan?
Pra_A

1
Saya telah mencoba solusi ini tetapi memperkenalkan preblem yang sangat serius, saya menggunakan kode ini untuk mencatat info permintaan di dalam filter oncePerRequest, dan ketika saya menggunakannya, semua @modelAttribute saya yang mengikat di semua metode posting saya memberi nol di semua bidang objek. Saya tidak merekomendasikan menggunakan pendekatan ini.
Mohammed Fathi

Haruskah kita tidak menutup pembaca?
aristo_sh

46

Cara mudah dengan commons-io.

IOUtils.toString(request.getReader());

https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/IOUtils.html


Saya akan membantu jika Anda dapat memberikan contoh bagaimana keluaran pembaca akan terlihat (yaitu, tunjukkan kunci atau tidak)
ArthurG

Ini berhasil untuk saya. Saya dapat mengonfirmasi bahwa solusi ini juga menghindari skenario umum di mana bufferedreader.readLine () "hang" tanpa alasan yang jelas
Naren

Hai @DavidDomingo, ini berfungsi 100%, saya dapat membaca bahwa Anda mengomentari hal yang sama dalam tanggapan di atas yang satu ini (yang juga berfungsi). Periksa bahwa di suatu tempat dalam kode Anda (memfilter dengan masalah), atau mungkin karena seseorang oleh Spring, metode getReader () tidak dipanggil sebelumnya, karena jika Anda memanggilnya dua kali atau lebih, itu hanya mengembalikan payload yang pertama.
Dani

Hai @Dani, itu sebabnya tidak berhasil. Pembaca kosong. Saya pikir RestController membacanya sebelum Anda dapat melakukannya di titik akhir mana pun. Cara termudah untuk mendapatkan body adalah dengan menggunakan HttpEntity.
David Domingo

31

Ketahuilah, kode Anda cukup berisik. Saya tahu utasnya sudah tua, tetapi banyak orang akan tetap membacanya. Anda dapat melakukan hal yang sama menggunakan pustaka jambu biji dengan:

    if ("POST".equalsIgnoreCase(request.getMethod())) {
        test = CharStreams.toString(request.getReader());
    }

3
Mungkin pertimbangkanif(RequestMethod.POST.name().equalsIgnoreCase(...)) { ... }
Madbreaks

Saya mendapatkan java.lang.IllegalStateException: getReader () telah dipanggil untuk permintaan ini
Pra_A

18

Jika yang Anda inginkan hanyalah badan permintaan POST, Anda dapat menggunakan metode seperti ini:

static String extractPostRequestBody(HttpServletRequest request) throws IOException {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

Kredit ke: https://stackoverflow.com/a/5445161/1389219


1
Mempertimbangkan bahwa request.getInputStream()tidak menghormati pengkodean karakter permintaan seperti request.getReader()halnya. 1 untuk tautannya.
Vadzim

apa yang harus setara untuk metode PUT?
devanathan

10

Ini berfungsi untuk GET dan POST:

@Context
private HttpServletRequest httpRequest;


private void printRequest(HttpServletRequest httpRequest) {
    System.out.println(" \n\n Headers");

    Enumeration headerNames = httpRequest.getHeaderNames();
    while(headerNames.hasMoreElements()) {
        String headerName = (String)headerNames.nextElement();
        System.out.println(headerName + " = " + httpRequest.getHeader(headerName));
    }

    System.out.println("\n\nParameters");

    Enumeration params = httpRequest.getParameterNames();
    while(params.hasMoreElements()){
        String paramName = (String)params.nextElement();
        System.out.println(paramName + " = " + httpRequest.getParameter(paramName));
    }

    System.out.println("\n\n Row data");
    System.out.println(extractPostRequestBody(httpRequest));
}

static String extractPostRequestBody(HttpServletRequest request) {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        Scanner s = null;
        try {
            s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s.hasNext() ? s.next() : "";
    }
    return "";
}

9

Jika isi permintaan kosong, itu berarti sudah dikonsumsi sebelumnya. Misalnya dengan panggilan request.getParameter(), getParameterValues()atau getParameterMap()panggilan. Hapus saja baris yang melakukan panggilan tersebut dari kode Anda.


Itu hanya berfungsi jika itu bukan unggahan file, seperti curlcontohnya, bukan?
Dave Newton

1
Saya mencoba hal ini. Tapi tetap saja saya belum mendapatkan badan POST. Saya pasti melewatkan sesuatu. Sekadar menambahkan: Saya menggunakan Tapestry untuk pengembangan.
patel bhavin

3

Ini akan bekerja untuk semua metode HTTP.

public class HttpRequestWrapper extends HttpServletRequestWrapper {
    private final String body;

    public HttpRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = IOUtils.toString(request.getReader());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getBody().getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {
            }

        };
        return servletInputStream;
    }

    public String getBody() {
        return this.body;
    }
}

0

Saya menyelesaikan situasi itu dengan cara ini. Saya membuat metode util yang mengembalikan objek yang diekstrak dari tubuh permintaan, menggunakan metode readValue dari ObjectMapper yang mampu menerima Reader.

public static <T> T getBody(ResourceRequest request, Class<T> class) {
    T objectFromBody = null;
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        HttpServletRequest httpServletRequest = PortalUtil.getHttpServletRequest(request);
        objectFromBody = objectMapper.readValue(httpServletRequest.getReader(), class);
    } catch (IOException ex) {
        log.error("Error message", ex);
    }
    return objectFromBody;
}

1
apa itu PortalUtil?
Ferry Kranenburg

Saya yakin ini dari Liferay, API khusus Liferay
mvmn
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.