คำอธิบายประกอบ @Valid ระบุอะไรในฤดูใบไม้ผลิ


88

ในตัวอย่างต่อไปนี้ScriptFileพารามิเตอร์ถูกทำเครื่องหมายด้วย@Validคำอธิบายประกอบ

อะไร@Validคำอธิบายประกอบทำอย่างไร

@RequestMapping(value = "/scriptfile", method = RequestMethod.POST)    
public String create(@Valid ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        
    if (result.hasErrors()) {        
        modelMap.addAttribute("scriptFile", scriptFile);            
        modelMap.addAttribute("showcases", ShowCase.findAllShowCases());            
        return "scriptfile/create";            
    }        
    scriptFile.persist();        
    return "redirect:/scriptfile/" + scriptFile.getId();        
}    

คำตอบ:


63

เพื่อวัตถุประสงค์ในการตรวจสอบความถูกต้อง

การตรวจสอบความถูกต้องเป็นเรื่องปกติที่จะตรวจสอบความถูกต้องของโมเดลหลังจากเชื่อมโยงอินพุตของผู้ใช้กับมัน Spring 3 ให้การสนับสนุนสำหรับการยืนยันแบบเปิดเผยด้วย JSR-303 การสนับสนุนนี้จะเปิดใช้งานโดยอัตโนมัติหากผู้ให้บริการ JSR-303 เช่น Hibernate Validator มีอยู่ใน classpath ของคุณ เมื่อเปิดใช้งานคุณสามารถทริกเกอร์การตรวจสอบความถูกต้องได้ง่ายๆโดยใส่คำอธิบายประกอบพารามิเตอร์วิธีการควบคุมด้วยคำอธิบายประกอบ @Valid: หลังจากเชื่อมโยงพารามิเตอร์ POST ที่เข้ามาแล้ว AppointmentForm จะได้รับการตรวจสอบความถูกต้อง ในกรณีนี้เพื่อตรวจสอบว่าค่าฟิลด์วันที่ไม่เป็นโมฆะและเกิดขึ้นในอนาคต


ดูข้อมูลเพิ่มเติมที่นี่:
http://blog.springsource.com/2009/11/17/spring-3-type-conversion-and-validation/


37

การเพิ่มคำตอบข้างต้นลองดูที่คำตอบต่อไปนี้ AppointmentForm's dateคอลัมน์ข้อเขียนกับคู่ของคำอธิบายประกอบ โดยมี@Validคำอธิบายประกอบที่ทริกเกอร์การตรวจสอบความถูกต้องบนAppointmentForm(ในกรณีนี้@NotNullและ@Future) คำอธิบายประกอบเหล่านี้อาจมาจากผู้ให้บริการ JSR-303 ที่แตกต่างกัน (เช่น Hibernate, Spring..etc)

    @RequestMapping(value = "/appointments", method = RequestMethod.POST)
    public String add(@Valid AppointmentForm form, BindingResult result) {
        ....
    }

    static class AppointmentForm {

        @NotNull @Future
        private Date date;
    }

1
ฉันมีรหัสที่คล้ายกัน ผมได้ออก@ValidในApplicationFormพารามิเตอร์ แต่การตรวจสอบยังคงถูกยิงdate(ตั้งค่าเป็นnull) ฟิลด์ กรุณาอธิบาย.
lupchiazoem

18

@Validในตัวมันเองไม่มีอะไรเกี่ยวข้องกับฤดูใบไม้ผลิ เป็นส่วนหนึ่งของข้อกำหนดเกี่ยวกับการตรวจสอบความถูกต้องของถั่ว (มีหลายรายการโดยล่าสุดคือ JSR 380 ในช่วงครึ่งหลังของปี 2560) แต่@Validเก่ามากและมาจาก JSR 303

อย่างที่เราทุกคนทราบกันดีว่า Spring มีความสามารถในการผสานรวมกับ JSR และไลบรารี java ที่แตกต่างกันโดยทั่วไป (ลองนึกถึง JPA, JTA, Caching และอื่น ๆ ) และแน่นอนว่าคนเหล่านั้นก็ดูแลการตรวจสอบความถูกต้องด้วยเช่นกัน หนึ่งในองค์ประกอบที่สำคัญที่อำนวยความสะดวกในนี้เป็นMethodValidationPostProcessor

พยายามตอบคำถามของคุณ - @Validมีประโยชน์มากสำหรับสิ่งที่เรียกว่าการเรียงซ้อนการตรวจสอบความถูกต้องเมื่อคุณต้องการตรวจสอบความถูกต้องของกราฟที่ซับซ้อนไม่ใช่แค่องค์ประกอบระดับบนสุดของวัตถุ @Validเวลาที่คุณต้องการไปลึกทุกท่านต้องใช้ นั่นคือสิ่งที่ JSR กำหนด Spring จะปฏิบัติตามนั้นด้วยการเบี่ยงเบนเล็กน้อยบางอย่าง (ตัวอย่างเช่นฉันพยายามใส่@Validatedแทน@Validวิธี RestController และการตรวจสอบความถูกต้องได้ผล แต่จะใช้ไม่ได้กับถั่ว "บริการ" ปกติ)


แต่สิ่งที่ตรวจสอบความถูกต้อง?
nephewtom

กรุณาอธิบายให้ละเอียด @nephewtom คุณต้องการชี้แจงอะไร?
yuranos

ผมอ่าน JSR 303: ถั่วการตรวจสอบbeanvalidation.org/1.0/specScriptFile scriptFileแต่ยังคงฉันไม่ได้รับการตรวจสอบสิ่งที่จะได้รับการดำเนินการเกี่ยวกับ
nephewtom

ScriptFile ข้างในมันอาจจะมีฟิลด์มากมายและฟิลด์เหล่านั้นก็มีคำอธิบายประกอบอยู่ด้วยเช่นกัน นี่คือจุดเริ่มต้นของการตรวจสอบความถูกต้องจากคำถามเดิมไม่ชัดเจนว่าอะไรอยู่ในคลาส ScriptFile
yuranos

โอเคขอบคุณ. คุณช่วยยกตัวอย่างของสิ่งที่ตรวจสอบความถูกต้องได้ไหมว่าฟิลด์ของมันอยู่ที่ String, Integer และ Bean หรือไม่?
nephewtom

17

IIRC @Valid ไม่ใช่คำอธิบายประกอบ Spring แต่เป็นคำอธิบายประกอบ JSR-303 (ซึ่งเป็นมาตรฐาน Bean Validation) โดยทั่วไปจะตรวจสอบว่าข้อมูลที่คุณส่งไปยังเมธอดนั้นถูกต้องหรือไม่ (จะตรวจสอบความถูกต้องของ scriptFile ให้คุณ)


2
"มันจะตรวจสอบ scriptFile ให้คุณ" หมายความว่าอย่างไร ตรวจสอบว่ามันไม่เป็นโมฆะมีไวยากรณ์หรือเนื้อหาบางส่วน? กล่าวอีกนัยหนึ่งมันตรวจสอบอะไรได้บ้างและอย่างไร? ผู้ใช้ควรนำบางสิ่งไปใช้หรือไม่? ฉันจะหาข้อมูลเกี่ยวกับเรื่องนี้ได้ที่ไหน ขอขอบคุณ!
nephewtom

กรุณาตอบคำถามของ @ nephewtom มันไม่เพียงพอที่จะตรวจสอบความถูกต้องกับประเด็นหลักที่ขาดหายไปนั่นคือ "เทียบกับอะไร"?
monami

2
public String create(@Valid @NotNull ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        

ฉันเดาว่า@NotNullคำอธิบายประกอบนี้ถูกต้องดังนั้นหากไม่ต้องการเงื่อนไข


2

ฉันคิดว่าฉันรู้ว่าคำถามของคุณมุ่งหน้าไปทางไหน และเนื่องจากคำถามนี้เป็นคำถามที่ป๊อปอัปในผลการค้นหาหลักของ Google ฉันจึงสามารถตอบได้อย่างชัดเจนว่าคำอธิบายประกอบ @Valid ทำอะไรได้บ้าง

ฉันจะนำเสนอ 3 สถานการณ์เกี่ยวกับวิธีที่ฉันใช้ @Valid

รุ่น:

public class Employee{
private String name;
@NotNull(message="cannot be null")
@Size(min=1, message="cannot be blank")
private String lastName;
 //Getters and Setters for both fields.
 //...
}

JSP:

...
<form:form action="processForm" modelAttribute="employee">
 <form:input type="text" path="name"/>
 <br>
 <form:input type="text" path="lastName"/>
<form:errors path="lastName"/>
<input type="submit" value="Submit"/>
</form:form>
...

ตัวควบคุมสำหรับสถานการณ์ที่ 1:

     @RequestMapping("processForm")
        public String processFormData(@Valid @ModelAttribute("employee") Employee employee){
        return "employee-confirmation-page";
    }

ในสถานการณ์นี้หลังจากส่งแบบฟอร์มของคุณโดยมีช่อง lastName ว่างเปล่าคุณจะได้รับหน้าแสดงข้อผิดพลาดเนื่องจากคุณใช้กฎการตรวจสอบความถูกต้อง แต่คุณไม่ได้ดำเนินการใด ๆ

ตัวอย่างข้อผิดพลาดดังกล่าว: หน้าข้อยกเว้น

ตัวควบคุมสำหรับสถานการณ์ที่ 2:

 @RequestMapping("processForm")
    public String processFormData(@Valid @ModelAttribute("employee") Employee employee,
BindingResult bindingResult){
                return bindingResult.hasErrors() ? "employee-form" : "employee-confirmation-page";
            }

ในสถานการณ์นี้คุณกำลังส่งผลลัพธ์ทั้งหมดจากการตรวจสอบความถูกต้องนั้นไปยัง bindingResult ดังนั้นคุณจึงต้องตัดสินใจว่าจะทำอย่างไรกับผลการตรวจสอบความถูกต้องของแบบฟอร์มนั้น

ตัวควบคุมสำหรับสถานการณ์ที่ 3:

@RequestMapping("processForm")
    public String processFormData(@Valid @ModelAttribute("employee") Employee employee){
                return "employee-confirmation-page";
            }
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> invalidFormProcessor(MethodArgumentNotValidException ex){
  //Your mapping of the errors...etc
}

ในสถานการณ์สมมตินี้คุณยังไม่ได้จัดการข้อผิดพลาดเหมือนในสถานการณ์แรก แต่คุณส่งต่อไปยังวิธีการอื่นที่จะดูแลข้อยกเว้นที่@Validทริกเกอร์เมื่อประมวลผลโมเดลฟอร์ม ตรวจสอบสิ่งนี้เพื่อดูว่าจะทำอย่างไรกับการทำแผนที่และทั้งหมดนั้น

ในการสรุป : @Valid ด้วยตัวเองโดยไม่ต้องทำอะไรเพิ่มเติมที่ทริกเกอร์การตรวจสอบความถูกต้องของฟิลด์คำอธิบายประกอบ JSR 303 ( @NotNull, @Email, @Size ฯลฯ ... ) คุณยังต้องระบุกลยุทธ์ว่าจะทำอย่างไร ด้วยผลการตรวจสอบดังกล่าว

หวังว่าฉันจะสามารถเคลียร์บางสิ่งบางอย่างสำหรับคนที่อาจสะดุดกับเรื่องนี้


1

เพียงแค่เพิ่มคำตอบข้างต้นในโปรแกรมเว็บ @validจะใช้ที่ถั่วมีการตรวจสอบนอกจากนี้ยังมีคำอธิบายประกอบกับการตรวจสอบคำอธิบายประกอบเช่น@NotNull, @Email(จำศีลคำอธิบายประกอบ) ดังนั้นเมื่อขณะที่ได้รับข้อมูลจากผู้ใช้ค่าที่สามารถตรวจสอบได้และมีผลผูกพันผลจะมีการตรวจสอบ ผล. bindingResult.hasErrors()จะบอกได้ว่าการตรวจสอบใด ๆ ล้มเหลว


1

อีกแง่มุมหนึ่งที่มีประโยชน์ของ @Valid ที่ไม่ได้กล่าวถึงข้างต้นก็คือ (กล่าวคือ: การใช้บุรุษไปรษณีย์เพื่อทดสอบจุดสิ้นสุด) @Valid จะจัดรูปแบบผลลัพธ์ของการเรียก REST ที่ไม่ถูกต้องเป็น JSON ที่จัดรูปแบบแทนที่จะเป็นหยดของข้อความที่อ่านแทบไม่ได้ สิ่งนี้มีประโยชน์มากหากคุณกำลังสร้าง API ที่ใช้งานได้ในเชิงพาณิชย์สำหรับผู้ใช้ของคุณ


1

ฉันต้องการเพิ่มรายละเอียดเกี่ยวกับวิธีการ@Validทำงานโดยเฉพาะอย่างยิ่งในฤดูใบไม้ผลิ

ทุกสิ่งที่คุณต้องการทราบเกี่ยวกับการตรวจสอบความถูกต้องในฤดูใบไม้ผลิมีการอธิบายไว้อย่างชัดเจนและมีรายละเอียดในhttps://reflectoring.io/bean-validation-with-spring-boot/แต่ฉันจะคัดลอกคำตอบสำหรับวิธีการ@Validทำงานในลิงก์ ลงไป

@Validคำอธิบายประกอบสามารถเพิ่มให้กับตัวแปรในวิธีการควบคุมการตรวจสอบส่วนที่เหลือพวกเขา ตัวแปรที่สามารถตรวจสอบได้มี 3 ประเภท:

  • ร่างกายร้องขอ
  • ตัวแปรภายในเส้นทาง (เช่น id in / foos / {id}) และ
  • พารามิเตอร์การค้นหา

ตอนนี้ ... ฤดูใบไม้ผลิ "ตรวจสอบ" อย่างไร? คุณสามารถกำหนดข้อ จำกัด ให้กับฟิลด์ของคลาสโดยใส่คำอธิบายประกอบด้วยคำอธิบายประกอบบางอย่าง จากนั้นคุณส่งออบเจ็กต์ของคลาสนั้นไปยัง Validator ซึ่งจะตรวจสอบว่าตรงตามข้อ จำกัด หรือไม่

ตัวอย่างเช่นสมมติว่าฉันมีวิธีการควบคุมดังนี้:

@RestController
class ValidateRequestBodyController {

  @PostMapping("/validateBody")
  ResponseEntity<String> validateBody(@Valid @RequestBody Input input) {
    return ResponseEntity.ok("valid");
  }

}

ดังนั้นนี่คือคำขอ POST Inputซึ่งจะใช้เวลาในการตอบสนองของร่างกายและเราทำแผนที่กำลังที่ร่างกายตอบสนองต่อชั้นเรียน

นี่คือชั้นเรียนInput:

class Input {

  @Min(1)
  @Max(10)
  private int numberBetweenOneAndTen;

  @Pattern(regexp = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$")
  private String ipAddress;
  
  // ...
}

คำอธิบายประกอบ @Valid จะบอกให้สปริงไปและตรวจสอบความถูกต้องของข้อมูลที่ส่งผ่านไปยังคอนโทรลเลอร์โดยตรวจสอบเพื่อดูว่าจำนวนเต็ม numberBetweenOneAndTenอยู่ระหว่าง 1 ถึง 10 รวมกันเนื่องจากคำอธิบายประกอบขั้นต่ำและสูงสุดเหล่านั้น นอกจากนี้ยังตรวจสอบด้วยว่าที่อยู่ IP ที่ส่งเข้ามาตรงกับนิพจน์ทั่วไปในคำอธิบายประกอบ

หมายเหตุด้านข้าง: นิพจน์ทั่วไปไม่สมบูรณ์แบบ .. คุณสามารถส่งผ่านตัวเลข 3 หลักที่มากกว่า 255 และยังคงตรงกับนิพจน์ทั่วไป


นี่คือตัวอย่างของการตรวจสอบความถูกต้องของตัวแปรคิวรีและตัวแปรเส้นทาง:

@RestController
@Validated
class ValidateParametersController {

  @GetMapping("/validatePathVariable/{id}")
  ResponseEntity<String> validatePathVariable(
      @PathVariable("id") @Min(5) int id) {
    return ResponseEntity.ok("valid");
  }
  
  @GetMapping("/validateRequestParameter")
  ResponseEntity<String> validateRequestParameter(
      @RequestParam("param") @Min(5) int param) { 
    return ResponseEntity.ok("valid");
  }
}

ในกรณีนี้เนื่องจากตัวแปรแบบสอบถามและตัวแปรเส้นทางเป็นเพียงจำนวนเต็มแทนของการเรียนที่ซับซ้อนเพียงแค่เราใส่คำอธิบายประกอบข้อ จำกัดทางด้านขวาบนพารามิเตอร์แทนการใช้@Min(5)@Valid

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