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

在下面的示例中,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();
}
268140 次浏览

这是为了验证。

验证一个 在将用户输入绑定到模型之后。 Spring 3提供了对以下内容的支持 使用 JSR-303进行声明性验证。 这种支持是自动启用的 如果 JSR-303提供程序,例如 Hibernate Validator 正在播放 您的类路径。当启用时,您可以 简单地触发验证 标注 Controller 方法 parameter with the @Valid annotation: 绑定传入的 POST 之后 参数,则预约表格将 被验证; 在这种情况下,验证 日期字段值不为空,并且 发生在未来。


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

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

只是添加到上面的答案,在一个 Web 应用程序中 @valid用于需要验证的 bean 也需要注释验证注释的地方,例如 @NotNull@Email(hibernate 注释) ,所以当从用户那里获得输入时,值可以被验证,绑定结果将得到验证结果。 bindingResult.hasErrors()将告诉是否有任何验证失败。

除了上面的答案之外,还可以看看下面的内容。AppointmentFormdate列使用两个注释进行注释。通过使用 @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;
}
public String create(@Valid @NotNull ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {
if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");

I guess this @NotNull annotation is valid therefore if condition is not needed.

@Valid本身与 Spring 没有任何关系。它是 Bean 验证规范的一部分(有几个这样的规范,最新的一个是截至2017年下半年的 JSR 380) ,但是 @Valid非常古老,一直从 JSR 303派生而来。

众所周知,Spring 非常善于集成所有不同的 JSR 和 Java 库(想想 JPA、 JTA、缓存等等) ,当然这些家伙也负责验证。促进这一点的关键组件之一是 方法验证后处理器

尝试回答你的问题——当你想要验证一个复杂的图形而不仅仅是一个对象的顶层元素时,@Valid对于所谓的验证级联来说非常方便。每次你想深入,你必须使用 @Valid。这是 JSR 规定的。Spring 将遵守这一点,但有一些小的偏差(例如,我曾试图在 RestController 方法上使用 @Validated而不是 @Valid,验证工作也是如此,但是对于常规的“服务”bean 来说,情况并非如此)。

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

我知道你想问什么了。因为这个问题是在 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,等等..。)的验证的事情,您仍然需要指定一个如何处理所述验证结果的策略。

希望我能为那些可能被这个绊倒的人澄清一些事情。

我想添加更多关于 @Valid如何工作的细节,特别是在春天。

关于春季验证,您想知道的所有内容在 https://reflectoring.io/bean-validation-with-spring-boot/中都有清楚详细的解释,但是我将复制关于 @Valid如何工作的答案,以防链接出现故障。

可以将 @Valid注释添加到静息控制器方法中的变量中,以验证它们。有三种类型的变量可以验证:

  • 请求机构,
  • 路径中的变量(例如/fos/{ 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 注释将告诉 spring 去验证传递到控制器的数据,方法是检查整数 numberBetweenOneAndTen是否介于1和10之间,因为有那些最小和最大注释。它还将检查以确保传入的 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