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

发布于 2024-12-25 09:20:43 字数 695 浏览 2 评论 0原文

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

What configuration is needed to use annotations from javax.validation.constraints like @Size, @NotNull, etc.? Here's my code:

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

When I try to use it in another class, validation doesn't work (i.e. the object is created without error):

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

Why doesn't this apply constraints for id and name? What else do I need to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(23

叹梦 2025-01-01 09:20:43

要使 JSR-303 bean 验证在 Spring 中工作,您需要做一些事情:

  1. 注解的 MVC 命名空间配置:
  2. JSR-303 规范 JAR:validation -api-1.0.0.GA.jar (看起来你已经有了)
  3. 规范的实现,例如 Hibernate Validation,这似乎是最常用的示例: 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....
    }
}

For JSR-303 bean validation to work in Spring, you need several things:

  1. MVC namespace configuration for annotations: <mvc:annotation-driven />
  2. The JSR-303 spec JAR: validation-api-1.0.0.GA.jar (looks like you already have that)
  3. An implementation of the spec, such as Hibernate Validation, which appears to be the most commonly used example: hibernate-validator-4.1.0.Final.jar
  4. In the bean to be validated, validation annotations, either from the spec JAR or from the implementation JAR (which you have already done)
  5. In the handler you want to validate, annotate the object you want to validate with @Valid, and then include a BindingResult in the method signature to capture errors.

Example:

@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....
    }
}
情深缘浅 2025-01-01 09:20:43

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

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

然后,迭代违规集合,就可以找到违规行为。

You should use Validator to check whether you class is valid.

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

Then, iterating violations set, you can find violations.

青柠芒果 2025-01-01 09:20:43

几年后我来到这里,多亏了 atrain上面的评论。就我而言,我在接收用 @Size 注释的对象(在我的例子中为 POJO)的 API 中缺少 @Valid 。它解决了这个问题。

不需要需要向用@Size注释的变量添加任何额外的注释,例如@Valid@NotBlank code>,就是变量中的约束以及我在 API 中提到的内容...

Pojo 类:

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

API 类:

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

谢谢并欢呼

I come here some years after, and I could fix it thanks to atrain's comment above. In my case, I was missing @Valid in the API that receives the Object (a POJO in my case) that was annotated with @Size. It solved the issue.

I did not need to add any extra annotation, such as @Valid or @NotBlank to the variable annotated with @Size, just that constraint in the variable and what I mentioned in the API...

Pojo Class:

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

API Class:

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

Thanks and cheers

爱要勇敢去追 2025-01-01 09:20:43

就我而言,我使用的是 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>

In my case, I was using spring boot version 2.3.0. When I changed my maven dependency to use 2.1.3 it worked.

<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>
煮酒 2025-01-01 09:20:43

如果您想验证实体,则必须调用实体上的验证器。然后您将得到一组 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
}

You would have to call a Validator on the Entity if you want to validate it. Then you will get a set of ConstraintViolationException, which basically show for which field/s of your Entity there is a constraint violation and what exactly was it. Maybe you can also share some of the code you expect to validate your entity.

An often used technique is to do validation in @PrePersist and rollback transaction if using multiple data modifications during transaction or do other actions when you get a validation exception.

Your code should go like this:

@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
}
哥,最终变帅啦 2025-01-01 09:20:43

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

You can also simply use @NonNull with the lombok library instead, at least for the @NotNull scenario. More details: https://projectlombok.org/api/lombok/NonNull.html

天赋异禀 2025-01-01 09:20:43

就我而言,原因是 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,这对我有帮助。

In my case the reason was the hibernate-validator version.
Probably something is not supported in the newer version any more.

I changed:

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

I downgraded the version from 7.0.1.Final to 6.0.2.Final and this helped me.

黑寡妇 2025-01-01 09:20:43

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

只需将其从 ....-test 更改为 ...-validation 就可以了。

如果不将您使用的版本降级到 2.1.3 也可以解决该问题。

After the Version 2.3.0 the "spring-boot-strarter-test" (that included the NotNull/NotBlank/etc) is now "sprnig boot-strarter-validation"

Just change it from ....-test to ...-validation and it should work.

If not downgrading the version that you are using to 2.1.3 also will solve it.

零崎曲识 2025-01-01 09:20:43

我也面临同样的问题。 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>

I also faced the same problem. Javax annotations ( @NotNull, @Valid) were not performing any validation. Their presence was not making any difference.

I have to use 'springboot-starter-validation' dependency to make the javax validations effective.
Here is the related dependencies configuration. Also don't miss to add @Valid annotation on the Object you want to validate.

<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>
放赐 2025-01-01 09:20:43

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

You need to add @Valid to each member variable, which was also an object that contained validation constraints.

荭秂 2025-01-01 09:20:43

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

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>

Recently I faced the same. I upgraded hibernate-validator to ver 7.x but later I noticed this release note

Hibernate Validator 7.0 is the reference implementation for Jakarta Bean Validation 3.0.
The main change is that all the dependencies using javax. packages are now using jakarta.* packages.
Upgrade to Hibernate Validator 7 is only recommended if you are moving to Jakarta EE 9.

My project should target java 8, so keeping javax.validation instead of switiching to jakarta.validation, I've had to downgrade to

<dependency>
  <groupId>org.hibernate.validator</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>6.0.2.Final</version>
</dependency>
探春 2025-01-01 09:20:43

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

我在使用 kafka 侦听器时遇到了同样的问题,之后我用 @Validated 对其进行了注释,它开始工作。

@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) {

    }

}

By default javax validation in spring works for Rest controller method input variables. But for other places to use the same we have to annotate class containing @Valid annotation with @Validated class level annotation.

I was facing same issue with kafka listener and after that I annotated it with @Validated it started working.

@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) {

    }

}
无尽的现实 2025-01-01 09:20:43

如果您使用的是 Maven,只需在 pom.xml 的 tag 下添加以下内容即可。

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

对于 Gradle,您可以执行以下操作。

dependencies {
  ...
  implementation 'org.springframework.boot:spring-boot-starter-validation'
}

Just add the following in your pom.xml under tag if you are using Maven.

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

For Gradle you can do the following.

dependencies {
  ...
  implementation 'org.springframework.boot:spring-boot-starter-validation'
}
一口甜 2025-01-01 09:20:43

就我而言,我有一个未调用的自定义类级约束。

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

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

in my case i had a custom class-level constraint that was not being called.

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

as soon as i added a field-level constraint to my class, either custom or standard, the class-level constraint started working.

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

seems like buggy behavior to me but easy enough to work around i guess

鹿! 2025-01-01 09:20:43

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

So @Valid at service interface would work for only that object. If you have any more validations within the hierarchy of ServiceRequest object then you might to have explicitly trigger validations. So this is how I have done it:

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

}

You need to have following annotations at the object level if you want to trigger validation for that object.

@Valid
@NotNull
若水微香 2025-01-01 09:20:43

对于方法参数,您可以使用 Objects.requireNonNull() ,如下所示:
测试(字符串str){
Objects.requireNonNull(str);
}

但这仅在运行时检查,如果为 null,则抛出 NPE。这就像先决条件检查。但这可能就是您正在寻找的。

for method parameters you can use Objects.requireNonNull() like this:
test(String str) {
Objects.requireNonNull(str);
}

But this is only checked at runtime and throws an NPE if null. It is like a preconditions check. But that might be what you are looking for.

未蓝澄海的烟 2025-01-01 09:20:43

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。

Great answer from atrain,
but maybe better solution to catch exceptions is to utilize own HandlerExceptionResolver
and catch

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

Then you're able to keep your handler as clean as possible.
You don't need BindingResult, Model and SomeFormBean in myHandlerMethod anymore.

无需解释 2025-01-01 09:20:43

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

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

我正在使用 hibernate,所需的依赖项是:
依赖关系快照

*在“Spring & Hibernate 初学者”课程中拍摄的快照 @ Udemy

I came across this problem recently in a very similar situation:
Met all requirements as the top-rated answer listed but still got the wrong result.

So I looked at my dependencies and found I was missing some of them. I corrected it by adding the missing dependencies.

I was using hibernate, the required dependencies were:
Dependencies Snapshot

*Snapshot taken in class "Spring & Hibernate for Beginners" @ Udemy

鸩远一方 2025-01-01 09:20:43

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

If you are using lombok then, you can use @NonNull annotation insted.
or Just add the javax.validation dependency in pom.xml file.

叫思念不要吵 2025-01-01 09:20:43

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

致谢:- 来自 youtube 的评论。

For those who have not been able to perform server-side validation through Hibernate validation dependency.
Just remove Hibernate validator +javax validation dependency and add spring-boot-starter validation. It provides Hibernate Validator Internally, and it worked just fine for me.

Credits:- a comment from youtube.

太阳男子 2025-01-01 09:20:43

我遇到了同样的问题,但我得到了解决方案,

您的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>

第4步一样重要

I fell into the same issue, but I got solution

your servlet configuration xml file i.e {servlet-name}-servlet.xml file

should be like

    <?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>

step 4 is important one

软糖 2025-01-01 09:20:43

就我而言,当切换到 Spring 3 时。注释应该来自 jakarta。例如
反而
导入 javax.validation.constraints.Size;
导入 jakarta.validation.constraints.Size;

In my case when switching to the Spring 3. Annotations should be from jakarta. For example
Instead
import javax.validation.constraints.Size;
import jakarta.validation.constraints.Size;

汐鸠 2025-01-01 09:20:43

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

1-import javax.validation.constraints.NotNull;

2-导入javax.validation.constraints.Size;

3- @NotNull

4- @Size(最大 = 3)

In my case i removed these lines

1-import javax.validation.constraints.NotNull;

2-import javax.validation.constraints.Size;

3- @NotNull

4- @Size(max = 3)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文