来自 javax.validation.約束的注解不起作用

使用来自 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的约束? 我还需要做什么?

166344 次浏览

您应该使用 Validator 检查您的类是否有效。

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

然后,迭代冲突集,您可以找到冲突。

如果要验证该实体,请使用 需要打电话给验证者。然后您将得到一组 ConstraintViviationException,基本上是 显示您的实体的哪个字段/s 存在违反约束的情况,以及具体是什么情况。也许您还可以共享一些您希望验证实体的代码。

一种经常使用的技术是,如果在事务期间使用多个数据修改,或者在出现验证异常时执行其他操作,则在@PrePerist 和回滚事务中执行验证。

您的代码应该是这样的:

@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
}

要使 JSR-303 bean 验证在 Spring 中工作,您需要以下几点:

  1. 用于注释的 MVC 命名空间配置: <mvc:annotation-driven />
  2. JSR-303规范 JAR: validation-api-1.0.0.GA.jar(看起来您已经有了)
  3. 规范的实现,比如 Hibernate 验证,它似乎是最常用的例子: hibernate-validator-4.1.0.Final.jar
  4. 在要验证的 bean 中,验证注释,可以来自规范 JAR,也可以来自实现 JAR (您已经完成了)
  5. 在要验证的处理程序中,用 @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....
}
}

你也可以简单地使用 @NonNull龙目图书馆,至少是 @NotNull场景。更多细节: https://projectlombok.org/api/lombok/NonNull.html

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

@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;
}

在我看来是有问题的行为,但我想应该很容易解决

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

因此@Valid at 服务接口将仅适用于该对象。如果在 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

对于方法参数,您可以像下面这样使用 Objects.requNonNull () : Test (String str){ 必需的 NonNull (str) ; } 但是这只在运行时检查,如果为 null 则抛出 NPE。这就像一个先决条件检查。但这可能就是你想要的。

几年后我来到这里,我可以修复它感谢 火车以上评论。在我的例子中,接收使用 @Size注释的 Object (在我的例子中是 POJO)的 空气污染指数中缺少 @Valid。问题解决了。

我做了 没有需要添加任何额外的注释,如 @Valid@NotBlank到用 @Size注释的变量,只是在变量中的约束和我在 API 中提到的..。

Pojo 班级:

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

API 类别:

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

谢谢,干杯

火车的回答很棒, 但是也许捕捉异常的更好的解决方案是利用自己的 异常解决程序 接住

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

这样你就能让你的联络人尽可能干净。 在 myHandlerMethod 中不再需要 BindingResult、 Model 和 Some FormBean。

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

因此,我查看了我的依赖关系,发现其中一些缺失了。我通过添加缺少的依赖项来纠正它。

我正在使用 hibernate,所需的依赖项是: Dependencies Snapshot

* “ Spring & Hibernate for Beginners”@Udemy 课堂快照

在我的例子中,我使用的是 Spring 启动版本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>

在我的情况下,我删除了这些线

1-导入 javax.validation.約束.NotNull;

2-import javax.validation.約束

3 -@NotNull

4 -@大小(最大 = 3)

如果您正在使用 lombok,那么可以使用@NonNull 注释。 或者,只需在 pom.xml 文件中添加 javax.validationencyencyencyx.xml 文件。

在版本2.3.0之后,“ 弹簧-启动器-启动器-测试”(包括 NotNull/NotBlank/etc)现在是“ 启动启动器验证

只要把它从 测试改成 确认就可以了。

如果没有将您正在使用的版本降级到2.1.3,也可以解决这个问题。

对于那些无法通过 Hibernate 验证依赖性执行服务器端验证的用户。 只需删除 Hibernate 验证器 + javax 验证依赖项,并添加 spring-boot-starter 验证。它在内部提供 Hibernate 验证程序,对我来说它工作得很好。

来自 youtube 的评论。

我也面临着同样的问题。Javax 注释(@NotNull,@Valid)没有执行任何验证。他们的存在并没有起到任何作用。

我必须使用“ springboot-starter-validation”依赖项来使 javax 验证有效。 下面是相关的依赖关系配置。也不要错过在要验证的对象上添加@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>

在我的情况下,原因是 Hibernate-validator 版本。 可能有些东西在新版本中不再支持了。

我变了:

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

我把版本从 7.0.1. 决赛降级到 6.0.2. 最终版,这对我很有帮助。

最近我也遇到了同样的问题,我把 hibernate-validator升级到了7.x 版本,但是后来我注意到了这个 释放通知书

Hibernate Validator 7.0是 JakartaBean 验证3.0的参考实现。
主要的变化是使用 javax.package 的所有依赖项现在都使用 jakarta.* 包。
只有在迁移到 JakartaEE9时,才建议升级到 HibernateValidator7。

我的项目应该以 java8为目标,所以保持 javax.validation而不是切换到 jakarta.validation,我不得不降级到

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

默认情况下,Spring 中的 javax 验证适用于 REST 控制器方法输入变量。但是对于其他地方使用相同的注释,我们必须使用@Validedclass 级注释来注释包含@Valid 注释的类。

我在卡夫卡的听众中也遇到过同样的问题,在那之后我用@Validedit 进行了注释,它开始工作了。

@Component
@Log4j2
@Validated
public class KafkaMessageListeners {


@KafkaListener(topics = "message_reprocessor", errorHandler = "validationErrorHandler")
public void processMessage(@Payload @Valid CustomPojo payload,
@Header(KafkaHeaders.OFFSET) List<Long> offsets, Acknowledgment acknowledgment) {


}


}

我也遇到了同样的问题,但我找到了解决办法

您的 servlet 配置 xml 文件即{ servlet-name }-servlet.xml 文件

应该是这样

    <?xml version="1.0" encoding="UTF-8"?>
    

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    

<context:component-scan base-package = "spring.tutorial.controller" />
       

->>>  Step 4: Add support for conversion, formatting and validation support
       

<mvc:annotation-driven/>
    

<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name = "prefix" value = "/WEB-INF/views/" />
<property name = "suffix" value = ".jsp" />
</bean>
    

</beans>

第四步很重要