1. 概述
<em style="font-style: italic;">NullPointerException</em> 是一種常見問題。 通過向方法參數添加註解,如@NotNull`,我們可以保護我們的代碼。
通過使用 @<em style="font-style: italic;">NotNull</em>,我們表明我們絕不應該使用 null 調用我們的方法,以避免異常。 然而,僅此不足以解決問題。 讓我們來了解原因。
2. 方法參數上的 <em @NotNull 註解
首先,創建一個類,該類包含一個方法,該方法簡單地返回一個 <em @NotNull 字符串的長度。
讓我們為我們的參數添加 <em @NotNull 註解:
public class NotNullMethodParameter {
public int validateNotNull(@NotNull String data) {
return data.length();
}
}當我們在導入 NotNull, w 時,應注意,@NotNull 註解有多種實現。因此,我們需要確保它來自正確的包。
我們將使用 jakarta.validation.constraints 包。
現在,讓我們創建一個 NotNullMethodParameter 並用一個 null 參數調用我們的方法:
NotNullMethodParameter notNullMethodParameter = new NotNullMethodParameter();
notNullMethodParameter.doesNotValidate(null);儘管我們使用了 NotNull 註解,但我們仍然收到 NullPointerException:
java.lang.NullPointerException我們的標註沒有任何作用,因為沒有驗證器來強制執行它。
3. 添加驗證器
讓我們添加 Hibernate Validator,它是 jakarta.validation 的參考實現,用於識別我們的 @NotNull。
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>在依賴項已配置完成後,我們可以強制應用 @NotNull 註解。
因此,讓我們使用默認的 ValidatorFactory 創建一個驗證器:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();然後,讓我們將 驗證 為我們標註方法的首要步驟:
validator.validate(myString);現在,當我們調用帶有空參數的方法時,我們的 @NotNull 註解就會生效:
java.lang.IllegalArgumentException: HV000116: The object to be validated must not be null.這很好,但在每個註釋方法中添加調用我們的驗證器導致大量的冗餘代碼。
4. Spring Boot
幸運的是,我們可以在 Spring Boot 應用程序中使用一種更簡單的方法。
4.1. Spring Boot 驗證
首先,添加 Spring Boot 驗證所需的 Maven 依賴項:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>我們的 spring-boot-starter-validation 依賴引入了 Spring Boot 和驗證所需的一切。這意味着我們可以移除我們早期的 Hibernate 依賴,保持我們的 pom.xml 清潔。
現在,讓我們創建一個 Spring 管理的 Component,並確保添加了 @Validated 註解。 讓我們使用一個 validateNotNull 方法來創建它,該方法接受一個 String 參數並返回我們數據的長度,並使用 @NotNull 註解來標註我們的參數:
@Component
@Validated
public class ValidatingComponent {
public int validateNotNull(@NotNull String data) {
return data.length();
}
}最後,讓我們創建一個使用 ValidatingComponent自動注入的 SpringBootTest。我們還將添加一個方法參數為 null 的測試:
@SpringBootTest
class ValidatingComponentTest {
@Autowired ValidatingComponent component;
@Test
void givenNull_whenValidate_thenConstraintViolationException() {
assertThrows(ConstraintViolationException.class, () -> component.validate(null));
}
}我們得到的 ConstraintViolationException 包含我們的參數名稱和“不能為 null”的消息。
javax.validation.ConstraintViolationException: validate.data: must not be null我們可以在我們的方法約束文章中瞭解更多關於標註我們方法的信息。
4.2. 一些警告
儘管這對於我們的公共方法有效,但讓我們看看當我們添加一個未標記但調用我們原始標記方法的方法時會發生什麼:
public String callAnnotatedMethod(String data) {
return validateNotNull(data);
}我們的 NullPointerException 異常返回。 在從同一類中另一個方法調用註解方法時,Spring 不會強制執行 NotNull 約束。
4. 結論
在本文中,我們學習瞭如何在標準 Java 應用程序的方法參數上使用 <em @NotNull</em> 註解。我們還學習瞭如何使用 Spring Boot 的 <em @Validated</em> 註解來簡化 Spring Bean 方法參數驗證,同時還注意到其侷限性。