ChatGPT解决这个技术问题 Extra ChatGPT

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();        
}    

i
informatik01

这是出于验证目的。

验证 在将用户输入绑定到模型后验证模型是很常见的。 Spring 3 支持使用 JSR-303 进行声明式验证。如果您的类路径中存在 JSR-303 提供程序(例如 Hibernate Validator),则会自动启用此支持。启用后,您只需使用@Valid 注解注解Controller 方法参数即可触发验证:绑定传入的POST 参数后,AppointmentForm 将被验证;在这种情况下,要验证日期字段值不为空并且将来发生。


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


长话短说,在您的特定示例代码中,ScriptFile 类为类数据成员(如 @NotNull@NotEmpty 等)定义了一些约束,并且 @Valid 指示框架(在我们的例子中是 spring)在有人调用您的方法时根据提供的参数检查这些约束。在这种情况下,如果验证失败,服务器会以 HTTP 400 Bad Request 状态代码进行响应。
@EmreTapcı 如果我们不输入有效值会发生什么?它不会验证任何约束吗?
n
noob

添加到上述答案,看看以下。 AppointmentFormdate 列带有几个注释。通过在 AppointmentForm(在本例中为 @NotNull@Future)上触发验证的 @Valid 注释。这些注释可能来自不同的 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;
    }

我有一个类似的代码。我在 ApplicationForm 参数上删除了 @Valid,但仍然在 date(设置为 null)字段上触发了验证。请解释。
y
yuranos

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

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

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


但是,验证什么?
请详细说明,@nephewtom。你想澄清什么?
我阅读了 JSR 303:Bean 验证,beanvalidation.org/1.0/spec,但我仍然不知道将在 ScriptFile scriptFile 上执行什么验证。
它里面的 ScriptFile 可能有一堆字段,这些字段也有注释。这是验证开始的地方。根据原始问题,尚不清楚 ScriptFile 类中到底是什么。
好,谢谢。你能举一个例子来验证它的字段是否是字符串、整数和 Bean?
M
Mateusz Dymczyk

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


“它将为您验证 scriptFile”是什么意思?检查它不为空,它有一些语法,还是一些内容?换句话说,它验证什么以及如何验证?用户应该实现一些东西吗?我在哪里可以获得有关它的信息?谢谢!
请回答@nephewtom 的问题,用“反对什么”这一缺失的要点来验证是不够的?
S
SomeGuy

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

您想了解的有关春季验证的所有信息都在 https://reflectoring.io/bean-validation-with-spring-boot/ 中进行了清楚而详细的解释,但如果链接断开,我将复制 @Valid 如何工作的答案。

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

请求正文,

路径中的变量(例如 /foos/{id} 中的 id)和,

查询参数。

那么现在......弹簧如何“验证”?您可以通过使用某些注释来注释类的字段来定义对它们的约束。然后,将该类的一个对象传递给一个验证器,该验证器检查是否满足约束。

例如,假设我有这样的控制器方法:

@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 之间,因为这些 min 和 max 注释。它还将检查以确保传入的 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


> 所以这是一个包含响应主体的 POST 请求,我们将该响应主体映射到一个类 Input..... 不应该是包含“请求主体”的 POST 请求吗?
@sss:是的,那是一个错误。现在已经更正了
P
Pang
public String create(@Valid @NotNull ScriptFile scriptFile, BindingResult result, ModelMap modelMap) {    
    if (scriptFile == null) throw new IllegalArgumentException("A scriptFile is required");        

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


A
Alan Balderas Sánchez

我想我知道你的问题在哪里。由于这个问题是谷歌搜索主要结果中弹出的问题,我可以对@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";
    }

在这种情况下,在提交带有空姓氏字段的表单后,您将收到一个错误页面,因为您正在应用验证规则,但您并没有对其进行任何处理。

上述错误示例: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
}

在这种情况下,您仍然没有像第一种情况那样处理错误,而是将其传递给另一个方法,该方法将处理 @Valid 在处理表单模型时触发的异常。检查 this 了解如何处理映射等。

总结一下:@Valid 本身并不会触发验证 JSR 303 注释字段(@NotNull、@Email、@Size 等)的验证,您仍然需要指定要做什么的策略与所述验证的结果。

希望我能够为可能会遇到这种情况的人清除一些东西。


p
puneet goyal

只是添加到上面的答案中,在 Web 应用程序中使用 @valid,其中要验证的 bean 也使用验证注释进行注释,例如 @NotNull@Email(休眠注释),因此当从用户获取输入时,值可以被验证并且绑定结果将具有验证结果。 bindingResult.hasErrors() 将告知是否有任何验证失败。


S
Sean Gildea

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