@Valid注释在Spring中表示什么?

时间:2010-08-29 14:42:10

标签: java spring spring-mvc spring-annotations

在以下示例中,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();        
}    

9 个答案:

答案 0 :(得分:49)

用于验证目的。

  

验证通常验证a   绑定用户输入后的模型。   Spring 3提供支持   使用JSR-303进行声明性验证。   此支持自动启用   如果是JSR-303提供者,比如   Hibernate Validator存在于   你的类路径。启用后,您可以   简单地触发验证   注释Controller方法   带@Valid注释的参数:   绑定传入POST后   参数,AppointmentForm会   得到验证;在这种情况下,要验证   日期字段值不为null   发生在将来。


在这里查看更多信息:
http://blog.springsource.com/2009/11/17/spring-3-type-conversion-and-validation/

答案 1 :(得分:23)

添加以上答案,请看下面的内容。 AppointmentForm' date列标注了几个注释。通过@Valid注释触发AppointmentForm上的验证(在本例中为@NotNull@Future)。这些注释可能来自不同的JSR-303提供程序(例如,Hibernate,Spring ..等)。

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

    static class AppointmentForm {

        @NotNull @Future
        private Date date;
    }

答案 2 :(得分:14)

IIRC @Valid不是Spring注释,而是JSR-303注释(这是Bean Validation标准)。它的作用是基本检查您发送给方法的数据是否有效(它将为您验证scriptFile)。

答案 3 :(得分:11)

@Valid本身与Spring无关。它是Bean Validation规范的一部分(其中有几个,最新的一个是JSR 380,截至2017年下半年),但是@Valid非常老,并且从JSR 303一直派生。 / p>

众所周知,Spring非常擅长提供与所有不同的JSR和Java库的集成(想想JPA,JTA,Caching等),当然这些人也负责验证。促进这一点的关键组成部分之一是MethodValidationPostProcessor

尝试回答您的问题 - 当您想要验证复杂图形而不仅仅是对象的顶级元素时,@Valid对于所谓的验证级联非常方便。每次想要更深入时,都必须使用@Valid。这就是JSR所要求的。 Spring会遵循一些小的偏差(例如我尝试将@Validated而不是@Valid放在RestController方法和验证工作上,但同样不适用于常规"服务&#34 ;豆)。

答案 4 :(得分:2)

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

我想这个@NotNull注释是有效的,因此如果不需要条件。

答案 5 :(得分:1)

只需添加上述答案,即可在网络应用程序中使用 @valid用于要验证的bean也使用验证注释注释的地方,例如@NotNull@Email(hibernate注释)因此,当从用户获取输入时,可以验证值,并且绑定结果将具有验证结果。 bindingResult.hasErrors()将告知任何验证是否失败。

答案 6 :(得分:1)

我想我知道你的问题要去哪里。而且由于这个问题是在Google搜索的主要结果中弹出的,所以我可以就@Valid注释的作用给出一个简单的答案。

我将介绍有关如何使用@Valid的3种情况

型号:

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字段的表单后,您将得到一个错误页面,因为您正在应用验证规则,但未对其进行任何处理。

上述错误的示例: Exception page

方案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
}

在这种情况下,您仍然没有像在第一种情况下那样处理错误,但是将其传递给另一种方法,该方法将处理在处理表单模型时<​​strong> @Valid 触发的异常。检查this,了解如何处理映射以及所有这些操作。

总结:@Valid本身不会执行触发验证JSR 303注释字段( @ NotNull,@ Email,@ Size等的验证)的操作。 ),您仍然需要指定一种处理验证结果的策略。

希望我能够为可能会为此迷失方向的人们清除一些东西。

答案 7 :(得分:0)

@Valid的另一个方便的方面是上面没有提到的(即:使用Postman测试端点),@ Valid会将不正确的REST调用的输出格式化为格式化的JSON,而不是难以读懂的文本。如果您要为用户创建可商业使用的API,这将非常有用。

答案 8 :(得分:0)

我想添加更多有关@Valid工作原理的详细信息,尤其是在春季。

https://reflectoring.io/bean-validation-with-spring-boot/中清楚,详细地介绍了您想知道的有关春季验证的所有信息,但是如果链接断开,我将复制@Valid的工作原理。

可以将@Valid批注添加到rest控制器方法中的变量以对其进行验证。可以验证3种类型的变量:

  • 请求正文,
  • 路径中的变量(例如/ foos / {id}中的id)和
  • 查询参数。

那么现在...弹簧如何“验证”?您可以通过使用某些注释来对类的字段定义约束。然后,将该类的对象传递到Validator中,该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之间(包括10和10),从而告诉spring去验证传递到控制器中的数据。它还将检查以确保传入的IP地址与注释中的正则表达式匹配。

旁注:正则表达式不是完美的..您可以传入大于255的3位数字,但它仍然与正则表达式匹配。


下面是验证查询变量和路径变量的示例:

@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