1. 概述
驗證各種值的過程在軟件開發中至關重要。它確保流入我們應用程序的數據是正確的且一致的。驗證可以應用於任何數據類型,基於不同的因素。
在 Spring 中,驗證通過內置工具和註解進行簡化,從而可以輕鬆地實現強大的驗證邏輯。
在本教程中,我們將學習如何在 Spring 中驗證值的列表。我們還將探討僅允許特定值的用例。 通過利用標準和自定義驗證方法,我們可以保持數據完整性並確保應用程序的無縫功能。
2. 在 Spring 中設置驗證
為了啓用驗證,請確保我們 pom.xml 中包含以下依賴項:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>此依賴項將 Hibernate Validator 集成到我們的 Spring 應用程序中。
3. 驗證值列表
假設我們需要驗證員工角色的列表。每個角色都應以 ROLE_ 開頭。
因此,我們首先在 Employee DTO 類中添加一個變量用於角色:
@NotEmpty(message = "Roles list cannot be empty")
@Valid
private List<@Pattern(regexp = "ROLE_[A-Z]+",
message = "Each role must start with 'ROLE_' and contain uppercase letters only") String> roles;@NotEmpty 註解確保列表不為空,@Pattern 註解則驗證每個角色是否與指定格式匹配。
下一步是向控制器類添加一個方法,以便我們可以觸發驗證。
@PostMapping("/validateListAtService")
public ResponseEntity<String> validateRoles(@RequestBody @Validated Employee request) {
return ResponseEntity.ok("Roles are valid!");
}這裏,@Validated 註解確保 Spring 在 Employee 對象上執行驗證。
最後,我們可以有一個全局異常處理類來處理驗證錯誤:
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleValidationException(MethodArgumentNotValidException ex) {
return ex.getBindingResult()
.getFieldErrors()
.stream()
.map(e -> e.getDefaultMessage())
.collect(Collectors.joining(","));
}讓我們來理解一下注釋:
- @ExceptionHandler 註解指定了方法處理的異常類型。在本例中,它處理 MethodArgumentNotValidException,該異常在對帶有 @Valid 或 @Validated 註解的類參數進行驗證時失敗時拋出
- @ResponseStatus 設置響應的 HTTP 狀態碼。這裏,它發送一個 400 BAD REQUEST 狀態碼,指示客户端提供了無效數據
- MethodArgumentNotValidException 異常提供驗證錯誤詳情,包括驗證失敗的字段和相關的錯誤消息
現在,讓我們討論一個驗證錯誤可能發生的場景。
假設客户端發送包含無效數據請求:
{
"roles": ["admin", "ROLE_ADMIN,", ""]
}根據驗證規則,角色名稱必須以 ROLE_ 開頭,並且不能為空,因此響應如下所示:
Each role must start with 'ROLE_' and contain uppercase letters only採用全局異常處理器的關鍵優勢在於,它確保所有驗證錯誤都能保持一致的處理。它為客户端提供用户友好的反饋,並減少了樣板代碼,從而消除了單個控制器中錯誤處理邏輯的需求。
4. 限制值到預定義列表
迄今為止,我們已經看到了一種驗證值列表的方法。現在,讓我們考慮另一個場景,即輸入特定員工的部門列表。要實現此功能,我們將創建一個自定義註解,以驗證輸入的部門列表是否有效,即該列表是預定義的列表的一部分。
首先,我們創建一個自定義驗證註解:
@Constraint(validatedBy = AllowedValuesValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowedValues {
String message() default "Invalid value";
String[] values();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}讓我們來理解這段代碼:
- @Constraint:指定負責驗證註解邏輯的類(AllowedValuesValidator)
- @Target:限制註解可以應用於的位置(例如,字段或方法參數)
- @Retention:確保註解在運行時可用以進行驗證
- values:接受預定義的允許值以供驗證
- message:驗證失敗時自定義錯誤消息
- groups 和 payload:可選屬性,用於分組約束和自定義元數據
下一步是實現我們的驗證器:
public class AllowedValuesValidator implements ConstraintValidator<AllowedValues, List<String>> {
private List<String> allowedValues;
@Override
public void initialize(AllowedValues constraintAnnotation)
{
allowedValues = Arrays.asList(constraintAnnotation.values());
}
@Override
public boolean isValid(List<String> values, ConstraintValidatorContext context) {
return values != null && values.stream()
.allMatch(allowedValues::contains);
}
}initialize() 方法檢索@AllowedValues 註解中指定的允許值,並將它們存儲在一個列表中,isValid() 方法如果列表中所有元素都存在於 allowedValues 列表中,則返回 true。它還通過返回 false 來優雅地處理 null 輸入。
最後一步是應用我們的自定義註解到一個 List<String> ,該列表代表各種預定義的部門。
@NotEmpty(message = "Departments list cannot be empty")
@AllowedValues(values = {"Management", "Software Development", "DevOps", "Architect"}, message = "Invalid department provided")
private List<String> department;@NotEmpty 註解確保列表不為空。@AllowedValues 自定義註解指定了有效的角色,例如 Management、Software Development、DevOps 和 Architect。如果驗證失敗,它將返回自定義錯誤消息,內容為 Invalid role provided.
5. 結論
在本文中,我們學習瞭如何在 Spring 中驗證列表,包括僅允許特定值的場景。通過使用內置註解,如 <em @Pattern</em>>,以及自定義註解,我們可以以最小的努力確保應用程序的數據完整性。<em @Pattern</em>> 的靈活性也使其在各種上下文中驗證單個字段時非常有用。