รับข้อมูลการร้องขอจากคำขอ POST ใน Java servlet


113

ฉันมีไลบรารี javascript ที่ส่งคำขอ POST ไปยัง Java servlet ของฉัน แต่ในdoPostวิธีนี้ดูเหมือนว่าฉันไม่สามารถรับเนื้อหาของเพย์โหลดคำขอได้ ใน chrome Developer Tools เนื้อหาทั้งหมดอยู่ในส่วน Request Payload ในแท็บส่วนหัวและมีเนื้อหาอยู่และฉันรู้ว่าวิธี doPost ได้รับ POST แต่มันก็ว่างเปล่า

สำหรับHttpServletRequest วัตถุฉันจะรับข้อมูลในเพย์โหลดคำขอได้อย่างไร

การทำrequest.getParameter()หรือrequest.getAttributes() ทั้งสองอย่างไม่มีข้อมูล


คุณต้องระบุพารามิเตอร์เช่นถ้าคุณมีคำหลักในเนื้อหาให้ใช้ String keyword = request.getParameter ("คำหลัก");
justMe

มันน่าสนใจที่จะเห็นโค้ด JavaScript ที่ส่งคำขอ เห็นได้ชัดว่ามันเขียนพารามิเตอร์คำขอผิดวิธี
BalusC

@ Razh ใช่ฉันรู้ฉันแค่ระบุวิธีที่ฉันกำลังพยายาม BalusC ฉันใช้ไลบรารี resumable.js เพื่อจัดการการอัปโหลดไฟล์แบบแยก
Fasih Awan

4
หากฉันไม่เข้าใจผิดสิ่งสำคัญคือคุณต้องไม่ใช้ request.getParameter () ก่อนที่จะอ่านจากอินพุตสตรีมมิฉะนั้นจะไม่มีข้อมูล (อ่านแล้ว)
Jeach

คำตอบ:


110

คำตอบง่ายๆ:
ใช้ getReader () เพื่ออ่านเนื้อหาของคำขอ

ข้อมูลเพิ่มเติม:
มีสองวิธีในการอ่านข้อมูลในเนื้อหา:

  1. getReader()ส่งคืนBufferedReaderที่จะช่วยให้คุณสามารถอ่านเนื้อหาของคำขอ

  2. getInputStream()ส่งคืนServletInputStreamหากคุณต้องการอ่านข้อมูลไบนารี

หมายเหตุจากเอกสาร: "[ทั้งสองวิธี] อาจถูกเรียกให้อ่านเนื้อหาไม่ใช่ทั้งสองอย่าง"


4
ไม่มีปัญหามันซ่อนอยู่เล็กน้อย
davidfrancis

25
โพสต์นี้อาจมีประโยชน์หากคุณเพิ่งใช้สิ่งนี้ในตัวกรองและพบว่าไม่มีอะไรสามารถอ่านเนื้อหาได้อีก! natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html
JonnyRaa

นี่เป็นคำตอบที่แย่จริงๆ
SgtPooki

1
@SgtPooki อย่าลังเลที่จะเพิ่มเหตุผลสำหรับความคิดเห็นนั้นครับท่านที่ดีของฉัน!
davidfrancis

@davidfrancis ฉันไม่ได้พยายามตัดสินคุณเป็นการส่วนตัวที่นี่ แต่: คุณไม่ได้ระบุบริบท .. ไม่มีลิงค์ไปยังเอกสารไม่มีตัวอย่าง การตอบกลับความคิดเห็นของคุณดูเหมือนจะต้องใช้ความพยายามมากกว่าคำตอบ
SgtPooki

68
String payloadRequest = getBody(request);

โดยใช้วิธีนี้

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
คำนึงถึงสิ่งที่request.getInputStream()ไม่เป็นไปตามการเข้ารหัสอักขระคำขอเช่นเดียวกับที่request.getReader()ทำ ตัวอย่างนี้ใช้ชุดอักขระเริ่มต้นของระบบ
Vadzim

9
new BufferedReader(new InputStreamReader(request.getInputStream()))สามารถทำให้ง่ายขึ้นเพียงแค่request.getReader()บัฟเฟอร์แล้วและยังรักษาการเข้ารหัสคำขอ
Vadzim

1
ฉันพบว่าโซลูชันนี้มีประโยชน์เนื่องจากมีข้อยกเว้น: javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this requestเมื่อฉันเรียก getReader () อันเป็นผลมาจากการที่ผู้อ่านเปิดอยู่แล้ว
Benjamin Slabbert

52

คุณสามารถใช้ Buffer Reader จากการร้องขอเพื่ออ่าน

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

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

สิ่งนี้น่าสนใจ แต่ดูไม่ค่อยมีประสิทธิภาพในแง่ของการต่อสายอักขระ! วิธีนี้สามารถปรับปรุงได้หรือไม่?
davidfrancis

11
String body = request.getReader (). lines (). collect (Collectors.joining ()); อาจใช้งานได้ Collectors.joining ใช้ StringBuilder ภายใต้ประทุนอย่างเห็นได้ชัด
Oliver Kohll

3
ฉันคิดว่าควร request.getReader (). lines (). collect (join ("\ n")) เพื่อรักษา newlines
Michael Böckling

ใน java 8 สตรีมจะถูกประมวลผลแบบขนานดังนั้นจำเป็นต้องเพิ่ม sequential method มิฉะนั้นจะรวมส่วนของข้อมูลที่ไม่ถูกต้อง - String body = request.getReader (). lines (). sequential (). reduction (System.lineSeparator (), ( ตัวสะสมของจริง) -> ตัวสะสม + ของจริง)
Jatin Bodarya

2
คุณสามารถแทนที่(accumulator, actual) -> accumulator + actualด้วยString::concat.
shmosel



5

หากคุณสามารถส่งข้อมูลใน JSON ได้นี่เป็นวิธีที่สะดวกที่สุดในการอ่านเพลย์โหลด:

ตัวอย่างชั้นข้อมูล:

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

ตัวอย่าง payload (ตัวขอ):

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

รหัสเพื่ออ่านเพย์โหลดใน servlet (ต้องใช้ com.google.gson. *):

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

นั่นคือทั้งหมด สวยง่ายและสะอาด อย่าลืมตั้งค่าส่วนหัวประเภทเนื้อหาเป็น application / json


2

ใช้ Java 8 ลองกับทรัพยากร:

    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

คุณต้องการเท่านั้น

request.getParameterMap ()

สำหรับการรับ POST และ GET - พารามิเตอร์

วิธีนี้จะส่งกลับไฟล์Map<String,String[]>.

คุณสามารถอ่านพารามิเตอร์ในแผนที่โดย

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
ระวัง: พารามิเตอร์ที่มีอยู่เท่านั้นถ้าคุณใช้การเข้ารหัสapplication/x-www-form-urlencoded; สำหรับmultipart/form-dataคุณต้องเข้าถึงส่วนต่างๆของร่างกายrequest.getReader()และแยกวิเคราะห์ด้วยตนเอง
twonkeys
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.