在 Spring 中驗證值列表
1. 概述
驗證各種值的過程在軟體開發中至關重要。它確保流入我們應用程式的數據是正確且一致的。驗證可以基於不同因素應用於任何資料類型。
在 Spring 中,透過內建工具和註解簡化了驗證,使我們能夠輕鬆實現健壯的驗證邏輯。
在本教程中,我們將學習如何在 Spring 中驗證值清單。我們還將研究僅允許特定值的情況。透過利用標準和自訂驗證方法,我們可以維護資料完整性並確保整個應用程式的無縫功能。
2.在Spring中設定驗證
若要啟用驗證,請確保我們的pom.xml
中有以下相依性:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
此依賴項將 Hibernate Validator 整合到我們的 Spring 應用程式中。
3. 驗證值List
假設我們需要驗證員工角色清單。每個角色都應以ROLE_
開頭。
因此,首先,我們在Employee
DTO 類別中加入一個角色變數:
@NotEmpty(message = "Roles list cannot be empty")
@Valid
private List<@Pattern(regexp = "ROLE_[AZ]+",
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
:限制可以套用此註解的位置(例如,欄位或方法參數) -
@Retentio
n:確保註解在運行時可用於驗證 -
values
:接受一組預先定義的允許值進行驗證 -
message
:驗證失敗時的自訂錯誤訊息 -
groups
andpayload
:用於分組約束和自訂元資料的可選屬性
下一步是實作我們的驗證器:
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
註解中指定的允許值並將它們儲存在清單中,如果值清單中的所有元素都在allowedValues
清單中,則isValid()
方法傳回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 中驗證列表,包括僅允許使用特定值的場景。使用@Pattern
等內建註釋和自訂註釋,我們可以以最少的努力確保應用程式的資料完整性。 @Pattern
的靈活性也使其對於驗證各種上下文中的各個欄位非常有用。
與往常一樣,本文中提供的程式碼可以在 GitHub 上取得。