Nhận tải trọng yêu cầu từ yêu cầu POST trong Java servlet


113

Tôi có một thư viện javascript đang gửi một yêu cầu POST đến Java servlet của tôi, nhưng trong doPostphương thức này, tôi dường như không thể nhận được nội dung của tải trọng yêu cầu. Trong Công cụ dành cho nhà phát triển chrome, tất cả nội dung đều nằm trong phần Yêu cầu tải trọng trong tab tiêu đề và nội dung ở đó và tôi biết rằng ĐĂNG đang được nhận bằng phương thức doPost, nhưng nó chỉ xuất hiện trống.

Đối với HttpServletRequest đối tượng, tôi có thể lấy dữ liệu trong tải trọng yêu cầu bằng cách nào?

Làm request.getParameter()hoặc request.getAttributes() cả hai đều không có dữ liệu


bạn cần chỉ định tham số nào, ví dụ: nếu bạn có từ khóa trong nội dung, hãy sử dụng String keyword = request.getParameter ("keyword");
justMe

Sẽ rất thú vị khi thấy mã JavaScript gửi yêu cầu. Có vẻ như nó đang soạn các thông số yêu cầu sai cách.
BalusC

@Razh vâng, tôi biết, tôi chỉ đang chỉ định phương pháp tôi đang thử. BalusC Tôi đang sử dụng thư viện resumable.js đến tập tin cập nhật xử lý phân chia
Fasih Awan

4
Nếu tôi không nhầm, điều quan trọng là bạn KHÔNG sử dụng request.getParameter () trước khi đọc từ luồng đầu vào nếu không sẽ không có dữ liệu nào (đã đọc).
Jeach

Câu trả lời:


110

Câu trả lời đơn giản:
Sử dụng getReader () để đọc phần nội dung của yêu cầu

Thông tin thêm:
Có hai phương pháp để đọc dữ liệu trong nội dung:

  1. getReader()trả về một BufferedReader sẽ cho phép bạn đọc phần nội dung của yêu cầu.

  2. getInputStream()trả về một ServletInputStream nếu bạn cần đọc dữ liệu nhị phân.

Lưu ý từ tài liệu: "[Một trong hai phương pháp] có thể được gọi để đọc nội dung, không phải cả hai."


4
Không có vấn đề, nó một chút ẩn mà một
davidfrancis

25
Bài đăng này có thể hữu ích nếu bạn vừa mới sử dụng nó trong một bộ lọc và sau đó phát hiện ra không có gì khác có thể đọc lại nội dung! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa

Đây là một câu trả lời thực sự tồi tệ.
SgtPooki

1
@SgtPooki vui lòng thêm một số lý do cho nhận xét đó, thưa ngài!
davidfrancis

@davidfrancis Tôi không cố gắng đánh giá cá nhân bạn ở đây, nhưng: bạn đã không cung cấp ngữ cảnh .. không có liên kết đến tài liệu, không có ví dụ. Câu trả lời của bạn cho nhận xét của tôi dường như cần nhiều nỗ lực hơn chính câu trả lời.
SgtPooki

68
String payloadRequest = getBody(request);

Sử dụng phương pháp này

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

6
Hãy tính đến điều request.getInputStream()đó không tôn trọng mã hóa ký tự yêu cầu request.getReader(). Vì vậy, ví dụ này sử dụng bộ mã hệ thống mặc định.
Vadzim

9
new BufferedReader(new InputStreamReader(request.getInputStream()))có thể được đơn giản hóa để chỉ request.getReader()cái đó đã được lưu vào bộ đệm và cũng giữ nguyên mã hóa yêu cầu.
Vadzim

1
Tôi thấy giải pháp này hữu ích khi một ngoại lệ được đưa ra: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestkhi tôi gọi getReader () do trình đọc đã được mở.
Benjamin Slabbert

52

Bạn có thể sử dụng Buffer Reader từ yêu cầu để đọc

    // 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()

40

Java 8 luồng

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

Điều này thật thú vị, nhưng trông khá kém hiệu quả về mặt nối chuỗi! Bất kỳ cách nào có thể được cải thiện?
davidfrancis

11
String body = request.getReader (). Lines (). Collect (Collectors.joining ()); cũng có thể hoạt động. Collectors.joining sử dụng một StringBuilder dưới mui xe rõ ràng.
Oliver Kohll

3
Tôi nghĩ rằng nó nên request.getReader (). Lines (). Collect (join ("\ n")) để duy trì các dòng mới.
Michael Böckling

Trong java 8, luồng sẽ được xử lý song song vì vậy cần thêm phương thức tuần tự nếu không sẽ hợp nhất sai phần dữ liệu - String body = request.getReader (). Lines (). Sequential (). Reduce (System.lineSeparator (), ( bộ tích lũy, thực tế) -> bộ tích lũy + thực tế)
Jatin Bodarya

2
Bạn có thể thay thế (accumulator, actual) -> accumulator + actualbằng String::concat.
shmosel


12

Nếu nội dung của phần thân là một chuỗi trong Java 8, bạn có thể thực hiện:

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


5

Nếu bạn có thể gửi tải trọng trong JSON, đây là cách thuận tiện nhất để đọc tải trọng phát:

Lớp dữ liệu mẫu:

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

Tải trọng mẫu (nội dung yêu cầu):

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

Mã để đọc tải trọng trong servlet (yêu cầu com.google.gson. *):

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

Đó là tất cả. Đẹp, dễ dàng và sạch sẽ. Đừng quên đặt tiêu đề loại nội dung thành application / json.


2

Sử dụng Java 8 hãy thử với các tài nguyên:

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

1

Bạn chỉ cần

request.getParameterMap ()

để nhận POST và GET - Các thông số.

Phương thức trả về a Map<String,String[]>.

Bạn có thể đọc các thông số trong Bản đồ bằng cách

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

2
Lưu ý: Các tham số chỉ có sẵn nếu bạn sử dụng mã hóa application/x-www-form-urlencoded; vì multipart/form-data, bạn dường như cần truy cập vào phần cơ thể request.getReader()và phân tích cú pháp thủ công.
twonkeys
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.