javax.validation.constraints 中的注释不起作用

Posted

技术标签:

【中文标题】javax.validation.constraints 中的注释不起作用【英文标题】:Annotations from javax.validation.constraints not working 【发布时间】:2012-02-04 02:52:05 【问题描述】:

需要什么配置才能使用来自javax.validation.constraints 的注解,如@Size@NotNull 等?这是我的代码:

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Person 
      @NotNull
      private String id;

      @Size(max = 3)
      private String name;

      private int age;

      public Person(String id, String name, int age) 
        this.id = id;
        this.name = name;
        this.age = age;
      

当我尝试在另一个类中使用它时,验证不起作用(即对象创建时没有错误):

Person P = new Person(null, "Richard3", 8229));

为什么这不对idname 应用约束?我还需要做什么?

【问题讨论】:

这不是魔术,你需要配置一个验证器。这段代码在什么上下文中运行? 另请参考这个问题,它的答案可以避免手动检查 BindingResult 是否存在验证错误:***.com/questions/61992596/… 【参考方案1】:

要让 JSR-303 bean 验证在 Spring 中工作,您需要做几件事:

    注解的 MVC 命名空间配置:<mvc:annotation-driven /> JSR-303 规范 JAR:validation-api-1.0.0.GA.jar(看起来你已经有了) 规范的实现,例如 Hibernate Validation,这似乎是最常用的示例:hibernate-validator-4.1.0.Final.jar 在要验证的 bean 中,验证注释,来自规范 JAR 或实现 JAR(您已经完成) 在要验证的处理程序中,使用@Valid 注释要验证的对象,然后在方法签名中包含BindingResult 以捕获错误。

例子:

@RequestMapping("handler.do")
public String myHandler(@Valid @ModelAttribute("form") SomeFormBean myForm, BindingResult result, Model model) 
    if(result.hasErrors()) 
      ...your error handling...
     else 
      ...your non-error handling....
    

【讨论】:

这为我们提供了验证器的默认配置。现在,我想在使用验证器之前对其进行配置。我在哪里可以配置它?任何要实现的覆盖或要调用的设置器? 我遇到的问题是我没有意识到我需要在每个成员变量中添加@Valid,这也是一个包含验证约束的对象。 我已将 @Valid 添加到我的 RequestBody 中,但仍然没有调用约束。如果有任何冲突,我已经检查了依赖项。也解决了。不确定他们的问题是什么。我还检查了该字段是否应用了注释。已应用。 奇怪的是,我也满足了上述所有要点。验证仍然不起作用:(【参考方案2】:

你应该使用验证器来检查你的类是否有效。

Person person = ....;
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
Set<ConstraintViolation<Person>> violations = validator.validate(person);

然后,迭代违规集,就可以找到违规了。

【讨论】:

我认为,无论使用何种框架,这个问题都得到了完美的回答。谢谢..但我有一个疑问,我们如何在没有任何框架的情况下验证传递给某个方法的参数。例如test(@NotNull String str),我们可以为同一个写验证器吗?【参考方案3】:

就我而言,我使用的是 Spring Boot 2.3.0 版。当我将 maven 依赖项更改为使用 2.1.3 时,它起作用了。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>
</dependencies>

【讨论】:

从版本 2.3.0.RELEASE 开始 Spring Boot Web 和 WebFlux 启动器不再依赖验证启动器,因此您必须将 spring-boot-starter-validation 添加到您的 pom.xml 中。详情请查看 2.3.0 Release notes【参考方案4】:

如果要验证实体,必须调用实体上的验证器。然后,您将获得一组 ConstraintViolationException,它基本上显示您的实体的哪个/哪些字段存在约束违规以及它到底是什么。也许您还可以分享一些您希望验证实体的代码。

如果在事务期间使用多个数据修改或在遇到验证异常时执行其他操作,则经常使用的技术是在 @PrePersist 中进行验证并回滚事务。

你的代码应该是这样的:

@PrePersist
public void prePersist(SomeEntity someEntity)
    Validator validator = Validation.buildDefaultValidatorFactory.getValidator();
    Set<ConstraintViolation<SomeEntity>> = validator.validate(someEntity);
    //do stuff with them, like notify client what was the wrong field, log them, or, if empty, be happy

【讨论】:

【参考方案5】:

您也可以简单地将 @NonNulllombok 库 一起使用,至少 对于@NotNull 场景。更多详情:https://projectlombok.org/api/lombok/NonNull.html

【讨论】:

【参考方案6】:

几年后我来到这里,感谢atrain 的comment above,我可以修复它。在我的例子中,我在接收带有@Size 注释的对象(在我的例子中是 POJO)的 API 中缺少@Valid。它解决了这个问题。

我确实不需要需要为带有@Size注解的变量添加任何额外的注解,例如@Valid@NotBlank,只是变量中的那个约束和我在API...

Pojo 类:

...
@Size(min = MIN_LENGTH, max = MAX_LENGTH);
private String exampleVar;
...

API 类:

...
public void exampleApiCall(@RequestBody @Valid PojoObject pojoObject)
  ...

感谢和欢呼

【讨论】:

【参考方案7】:

在 2.3.0 版之后,“spring-boot-strarter-test”(包括 NotNull/NotBlank/等)现在是“sprnig boot-strarter-validation em>"

只需将其从 ....-test 更改为 ...-validation 即可。

如果不将你正在使用的版本降级到 2.1.3 也可以解决。

【讨论】:

【参考方案8】:

在我的例子中,我有一个没有被调用的自定义类级约束。

@CustomValidation // not called
public class MyClass 
    @Lob
    @Column(nullable = false)
    private String name;

只要我为我的类添加了一个字段级约束,无论是自定义的还是标准的,类级约束就开始起作用了。

@CustomValidation // now it works. super.
public class MyClass 
    @Lob
    @Column(nullable = false)
    @NotBlank // adding this made @CustomValidation start working
    private String name;

对我来说似乎是错误的行为,但我想很容易解决

【讨论】:

【参考方案9】:

您需要将@Valid添加到每个成员变量,这也是一个包含验证约束的对象。

【讨论】:

【参考方案10】:

我也遇到了同样的问题。 Javax 注释(@NotNull、@Valid)未执行任何验证。他们的存在并没有什么不同。

我必须使用“springboot-starter-validation”依赖项来使 javax 验证有效。 这里是相关的依赖配置。也不要错过在要验证的 Object 上添加 @Valid 注解。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.2</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
.....
.....
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
 <dependencies>

【讨论】:

【参考方案11】:

就我而言,原因是 hibernate-validator 版本。 可能新版本不再支持某些内容。

我变了:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>$hibernate-validator.version</version>
</dependency>

我将版本从 7.0.1.Final 降级为 6.0.2.Final,这对我有帮助。

【讨论】:

在尝试了一切之后,这是唯一有效的方法!谢谢【参考方案12】:

所以@Valid at service interface 只适用于那个对象。如果您在 ServiceRequest 对象的层次结构中有更多验证,那么您可能需要明确触发验证。所以这就是我的做法:

public class ServiceRequestValidator 

      private static Validator validator;

      @PostConstruct
      public void init()
         validator = Validation.buildDefaultValidatorFactory().getValidator();
      

      public static <T> void validate(T t)
        Set<ConstraintViolation<T>> errors = validator.validate(t);
        if(CollectionUtils.isNotEmpty(errors))
          throw new ConstraintViolationException(errors);
        
     


如果要触发对该对象的验证,则需要在对象级别具有以下注释。

@Valid
@NotNull

【讨论】:

【参考方案13】:

对于方法参数,您可以像这样使用 Objects.requireNonNull(): test(String str) Objects.requireNonNull(str); 但这仅在运行时检查,如果为空则抛出 NPE。这就像一个先决条件检查。但这可能是您正在寻找的。​​p>

【讨论】:

【参考方案14】:

atrain 给出了很好的回答, 但也许更好的捕获异常的解决方案是利用自己的 HandlerExceptionResolver 并抓住

@Override
public ModelAndView resolveException(
    HttpServletRequest aReq, 
    HttpServletResponse aRes,
    Object aHandler, 
    Exception anExc
)
    // ....
    if(anExc instanceof MethodArgumentNotValidException) // do your handle     error here

然后你就可以让你的处理程序尽可能的干净。 myHandlerMethod 中不再需要 BindingResult、Model 和 SomeFormBean。

【讨论】:

【参考方案15】:

我最近在非常相似的情况下遇到了这个问题: 满足列出的最受好评的答案的所有要求,但仍然得到错误的结果。

所以我查看了我的依赖项,发现我缺少其中的一些。我通过添加缺少的依赖项来纠正它。

我使用的是休眠,所需的依赖项是:

*在“Spring & Hibernate for Beginners”课堂上拍摄的快照@Udemy

【讨论】:

【参考方案16】:

如果您使用的是 lombok,则可以使用 @NonNull 注释。 或者只需在 pom.xml 文件中添加 javax.validation 依赖项。

【讨论】:

【参考方案17】:

对于那些无法通过 Hibernate 验证依赖执行服务器端验证的人。 只需删除 Hibernate 验证器 +javax 验证依赖并添加 spring-boot-starter 验证。它在内部提供了 Hibernate Validator,对我来说效果很好。

致谢:- 来自 youtube 的评论。

【讨论】:

【参考方案18】:

最近我也遇到了同样的情况。我将hibernate-validator 升级到了 7.x 版,但后来我注意到了这个release note

Hibernate Validator 7.0 是 Jakarta Bean Validation 3.0 的参考实现。 主要的变化是所有的依赖都使用了 javax.包现在使用 jakarta.* 包。 仅当您要迁移到 Jakarta EE 9 时,才建议升级到 Hibernate Validator 7。

我的项目应该针对 java 8,所以保留javax.validation 而不是切换到jakarta.validation,我不得不降级到

<dependency>
  <groupId>org.hibernate.validator</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>6.0.2.Final</version>
</dependency>

【讨论】:

【参考方案19】:

就我而言,我删除了这些行

1-导入 javax.validation.constraints.NotNull;

2-import javax.validation.constraints.Size;

3- @NotNull

4- @Size(max = 3)

【讨论】:

以上是关于javax.validation.constraints 中的注释不起作用的主要内容,如果未能解决你的问题,请参考以下文章