จะส่งคืนอะไรหากวิธีการควบคุม Spring MVC ไม่คืนค่า


137

ฉันใช้ jQuery $.getJSON()เพื่อโทรแบบอะซิงโครนัสไปยังแบ็กเอนด์ Spring MVC ของฉัน วิธีการควบคุม Spring ส่วนใหญ่มีลักษณะดังนี้:

@RequestMapping(value = "/someURL", method = RequestMethod.POST)
public @ResponseBody SomePOJO getSomeData(@ModelAttribute Widget widget,
    @RequestParam("type") String type) {
    return someDAO.getSomeData(widget, type);
}   

ฉันมีการตั้งค่าสิ่งต่างๆเพื่อให้คอนโทรลเลอร์แต่ละตัวส่งคืน@ResponseBodyเป็น JSON ซึ่งเป็นสิ่งที่ฝั่งไคลเอ็นต์คาดหวัง

แต่จะเกิดอะไรขึ้นเมื่อคำขอไม่ควรส่งคืนเนื้อหาใด ๆ ไปยังฝั่งไคลเอ็นต์ ฉันสามารถมี:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public @ResponseBody void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}

ถ้าไม่ไวยากรณ์ที่เหมาะสมที่จะใช้ที่นี่คืออะไร?


ฉันถือว่าถ้าคุณไม่คืนอะไรก็จะไม่มีการส่งเนื้อหาใด ๆ กลับมา?
ฮันต์

1
ฉันคิดว่าฉันยังคงส่งคืน POJO บางประเภทแม้ว่าในเวอร์ชัน 1 ของโซลูชันของคุณจะมีเพียงบูลีน "สำเร็จ" หรือสิ่งที่คล้ายกันก็ตาม แล้วคุณมีรูปแบบที่สอดคล้องกันในทุกวิธีการ AJAX ของคุณและสิ่งที่ง่ายที่จะสร้างในเมื่อมันเปิดออกคุณทำจำเป็นที่จะต้องมีอะไรบางอย่างกลับมา!
Millhouse

ตรงกันข้ามกับคำตอบที่เป็นข้อเสนอแนะสิ่งแรกที่คุณมีในตัวอย่างข้อมูลที่สองนั้นดีและเป็นวิธีที่ถูกต้องในการจัดการPOSTข้อมูล
Brett Ryan

ในกรณีนี้จะคืนค่าว่าง @RestController คลาสสาธารณะ RESTControllerExample {@RequestMapping (ค่า = "/ พนักงาน", method = RequestMethod.GET) โมฆะสาธารณะ getEmployeeNames () {EmployeeSource.getEmployees (); System.out.println ("ฉันเสร็จแล้ว"); }}
spandey

คำตอบ:


257

คุณสามารถคืนโมฆะได้จากนั้นคุณต้องทำเครื่องหมายวิธีการด้วย @ResponseStatus (value = HttpStatus.OK) คุณไม่ต้องการ @ResponseBody

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}

รับเฉพาะวิธีการคืนรหัสสถานะ 200 ความไม่สมบูรณ์เท่านั้นคนอื่น ๆ ทั้งหมดที่คุณทำหนึ่งในสามสิ่ง:

  • คืนโมฆะและทำเครื่องหมายวิธีการด้วย @ResponseStatus(value = HttpStatus.OK)
  • ส่งคืนวัตถุและทำเครื่องหมายด้วย @ResponseBody
  • ส่งคืนHttpEntityอินสแตนซ์

2
ในกรณีที่เกิดข้อยกเว้นรันไทม์ระหว่างนั้น HTTP 500 จะถูกส่งกลับไม่ใช่ 200 ดังนั้นหากการจัดการส่วนหน้าของคุณล้มเหลวข้อความข้อยกเว้น / ข้อผิดพลาดจะแสดงอย่างถูกต้อง
Lee Chee Kiam

27
จริงๆแล้วคุณไม่จำเป็นต้องตั้งค่า@ResponseStatusและไม่ควร เพียงมี@ResponseBodyในvoidการจัดการที่ดีก็พอ
Brett Ryan

11
ฉันคิดว่ามันจะดีกว่าที่จะส่งคืน No Content จำนวน 204 รายการแทนที่จะเป็น 200 สำหรับวิธีที่เป็นโมฆะ
raspacorp

1
@raspacorp 200 ถูกต้องสำหรับ POST เนื่องจากไม่ได้หมายถึงการมีร่างกาย
Brett Ryan

8
@BrettRyan เช่นเดียวกับความคิดเห็นอย่างน้อยสำหรับ REST API มันเป็นแนวทางปฏิบัติทั่วไปที่ POST จะถูกใช้สำหรับการสร้างเนื้อหาซึ่งในกรณีนี้มักจะส่งคืน id ของ enity ที่สร้างขึ้นเอนทิตีที่สร้างขึ้นแบบเต็มหรือลิงก์ เพื่อดำเนินการอ่าน การส่งคืนสถานะ 200 โดยไม่มีเนื้อหาอาจทำให้สับสนจากมุมมอง REST API
raspacorp

43

คุณสามารถส่งคืน ResponseEntity ด้วยส่วนหัวที่เหมาะสม:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public ResponseEntity updateDataThatDoesntRequireClientToBeNotified(...){
....
return new ResponseEntity(HttpStatus.OK)
}

ในกรณีที่มีใครประสบปัญหาเดียวกันกับที่ฉันทำสิ่งนี้ใช้ไม่ได้กับสปริงเวอร์ชันเก่า (4.1.1) ฉันจะได้รับข้อผิดพลาด 500 ข้อ ฉันอัปเกรดเป็น 4.2.0 และใช้งานได้ดี
ซอสเมื่อ

นั่นเป็นวิธีที่ฉันชอบในการคืนค่าว่างเปล่า 200 เช่นกัน ตั้งแต่ Spring 4.1 ใช้รูปแบบตัวสร้างแทน: return ResponseEntity.ok (). build ();
GreenTurtle

5
แม้ว่าดูเหมือนจะรวบรวม แต่ก็ให้คำเตือนต่อไปนี้ResponseEntity is a raw type. References to generic type ResponseEntity<T> should be parameterized
อนซาโล

8

คุณสามารถส่งคืนอ็อบเจ็กต์ "ResponseEntity" การใช้อ็อบเจกต์ "ResponseEntity" สะดวกมากทั้งในเวลาที่สร้างอ็อบเจ็กต์การตอบสนอง (ที่มี Response Body และ HTTP Status Code) และในเวลาที่รับข้อมูลออกจากอ็อบเจ็กต์การตอบสนอง

วิธีการเช่น getHeaders (), getBody (), getContentType (), getStatusCode () ฯลฯ ทำให้การอ่านวัตถุ ResponseEntity เป็นเรื่องง่ายมาก

คุณควรใช้อ็อบเจ็กต์ ResponseEntity ที่มีรหัสสถานะ http 204 (ไม่มีเนื้อหา) ซึ่งมีไว้เพื่อระบุว่าคำขอได้รับการประมวลผลอย่างถูกต้องและเนื้อหาการตอบกลับว่างเปล่าโดยเจตนา การใช้รหัสสถานะที่เหมาะสมเพื่อถ่ายทอดข้อมูลที่ถูกต้องเป็นสิ่งสำคัญมากโดยเฉพาะอย่างยิ่งหากคุณกำลังสร้าง API ที่จะใช้กับแอปพลิเคชันไคลเอนต์หลายตัว


3
การตั้งค่า@ResponseStatus(HttpStatus.NO_CONTENT)แก้ไขXML Parsing Error: no root element foundสำหรับฉันในเบราว์เซอร์
aliopi

3

ได้คุณสามารถใช้ @ResponseBody กับvoidreturn type:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
@ResponseBody
public void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}

1
แล้วผลตอบแทนจะเป็นแบบไหน .. มันคือรหัสสถานะ HTTP หรือเปล่า?
spandey

@techBeginner ในกรณีนี้คือ 200 (ตกลง)
Lakatos Gyula

2

ไม่มีอะไรผิดปกติกับการคืนโมฆะ@ResponseBodyและคุณควรPOSTร้องขอ

ใช้รหัสสถานะ HTTP เพื่อกำหนดข้อผิดพลาดภายในรูทีนตัวจัดการข้อยกเว้นแทนเนื่องจากคนอื่น ๆ กำลังกล่าวถึงสถานะความสำเร็จ วิธีการปกติตามที่คุณมีจะส่งคืนรหัสตอบกลับ200ซึ่งเป็นสิ่งที่คุณต้องการตัวจัดการข้อยกเว้นใด ๆ สามารถส่งคืนวัตถุข้อผิดพลาดและรหัสอื่น (เช่น500)


1

แต่เมื่อระบบของคุณมีขนาดและฟังก์ชันการทำงานที่เติบโตขึ้น ... ฉันคิดว่าการกลับ json อยู่เสมอไม่ใช่ความคิดที่แย่ เป็นเรื่องสถาปัตยกรรม / "การออกแบบขนาดใหญ่" มากกว่า

คุณสามารถคิดเกี่ยวกับการเก็บ JSON ไว้เสมอโดยมีช่องรู้สองช่อง ได้แก่ รหัสและข้อมูล โดยที่รหัสคือรหัสตัวเลขที่ระบุความสำเร็จของการดำเนินการที่จะทำและข้อมูลคือข้อมูลเชิงอนุพันธ์ใด ๆ ที่เกี่ยวข้องกับการดำเนินการ / บริการที่ร้องขอ

เมื่อเราใช้ผู้ให้บริการแบ็กเอนด์สามารถตรวจสอบบริการใด ๆ เพื่อดูว่าทำงานได้ดีหรือไม่

ดังนั้นฉันจึงยึดมั่นที่จะไม่ปล่อยให้สปริงจัดการสิ่งนี้โดยเปิดเผยการดำเนินการส่งคืนแบบไฮบริด (บางตัวส่งคืนข้อมูลอื่น ๆ ... ) .. ติดตั้งตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ของคุณเปิดเผยอินเทอร์เฟซที่เป็นเนื้อเดียวกันมากขึ้น ง่ายขึ้นในตอนท้ายของวัน


0

นี่คือตัวอย่างโค้ดที่ฉันทำกับเมธอดอะซิงโครนัส

@RequestMapping(value = "/import", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void importDataFromFile(@RequestParam("file") MultipartFile file) 
{
    accountingSystemHandler.importData(file, assignChargeCodes);
}

คุณไม่จำเป็นต้องส่งคืนสิ่งใด ๆ จากวิธีการของคุณทั้งหมดที่คุณต้องใช้คำอธิบายประกอบนี้เพื่อให้วิธีการของคุณกลับมาตกลงในทุกกรณี

@ResponseStatus(value = HttpStatus.OK)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.