1、概览 {#1概览}
空指针异常 NullPointerException
是一个常见问题,避免这种问题的方法之一是在方法参数上添加 @NotNull
等校验注解。
给方法参数添加了 @NotNull
注解后,还需要其他的一些设置才能自动对参数进行非空校验。
2、给方法参数添加 @NotNull
注解 {#2给方法参数添加-notnull-注解}
创建一个类,其中包含一个返回 String
长度的方法。
在 String
参数上添加 @NotNull
注解:
public class NotNullMethodParameter {
public int validateNotNull(@NotNull String data) {
return data.length();
}
}
注意,有多个包下都有 @NotNull
注解,我们使用的应该是 jakarta.validation.constraints
包。
创建 NotNullMethodParameter
实例,然后使用 null
参数调用方法。
NotNullMethodParameter notNullMethodParameter = new NotNullMethodParameter();
notNullMethodParameter.doesNotValidate(null);
尽管在参数上使用了 @NotNull
,但还是出现了空指针异常:NullPointerException
。
注解未生效,因为没有 Validator 来执行它。
3、添加 Validator {#3添加-validator}
添加 Hibernate Validator(jakarta.validation
的实现)来识别 @NotNull
。
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
使用默认的 ValidatorFactory
创建 validator。
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
然后,在第一行验证参数。
validator.validate(myString);
现在,当调用参数是 null
时,@NotNull
校验注解就会生效。
java.lang.IllegalArgumentException: HV000116: The object to be validated must not be null.
这种校验方式存在一个问题,就是几乎要在所有的方法中手动调用 Validator 来对参数进行校验。
4、Spring Boot {#4spring-boot}
如果是在 Spring Boot 应用中进行注解校验的话,一切就会变得简单多了。
4.1、Spring Boot Validation {#41spring-boot-validation}
首先,添加 spring-boot-starter-validation
依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.0.4</version>
</dependency>
先移除前面添加的 Hibernate
依赖,因为 spring-boot-starter-validation
已经包含校验所需要的一切依赖。
现在,创建一个由 Spring 管理的组件,并添加 @Validated
注解。添加一个 validateNotNull
方法,该方法接收一个 String
参数并返回其长度,同时用 @NotNull
对参数进行注解:
@Component
@Validated
public class ValidatingComponent {
public int validateNotNull(@NotNull String data) {
return data.length();
}
}
最后,创建一个 SpringBootTest
,并注入 ValidatingComponent
。
添加一个测试方法,使 null
作为参数进行调用。
@SpringBootTest
class ValidatingComponentTest {
@Autowired ValidatingComponent component;
@Test
void givenNull_whenValidate_thenConstraintViolationException() {
assertThrows(ConstraintViolationException.class, () -> component.validate(null));
}
}
校验生效,调用会失败,异常是:ConstraintViolationException
。
javax.validation.ConstraintViolationException: validate.data: must not be null
4.2、注意 {#42注意}
如果你在同一个类中,通过 this
直接调用使用了校验注解的方法,校验不会生效(由于 Spring 的代理机制)。
如下:
public String callAnnotatedMethod(String data) {
return validateNotNull(data);
}
这会直接导致 NullPointerException
异常。
4、总结 {#4总结}
本文介绍了如何在 Java 中使用 @NotNull
注解来对参数进行非空校验,以及如何在 Spring Boot 中使用 @Validated
注解来简化 Spring Bean 方法参数的验证。
参考:https://www.baeldung.com/java-notnull-method-parameter