使用 Spring Validator 介面進行驗證
一、簡介
Spring Validator介面提供了一種靈活且可自訂的方法來驗證物件。在本教程中,我們將探討如何使用Validator介面來驗證基於 Spring 的應用程式中的物件。
2.Spring Validator接口
Validator介面是 Spring 框架的一部分,提供了一種驗證物件的方法。
這是一個簡單的接口,定義了兩個方法, supports()和validate() 。這兩個方法用於確定驗證器是否可以驗證物件並執行驗證邏輯。
2.1. supports(Class<?> clazz)
Validator介面中的supports()方法決定驗證器是否可以驗證特定類別的實例。此方法接受參數Class<?> clazz ,它表示正在驗證的物件的類別。它是一個通用類別 ( Class<?> ),可以靈活地處理不同的物件類型。
具體來說,Spring 使用isAssignableFrom()方法來檢查一個物件是否可以合法地轉換為驗證器支援的類別的物件。因此,如果驗證器可以處理所提供的clazz的對象,則傳回true ,否則傳回false以指示應使用另一個驗證器:
@Override
public boolean supports(Class<?> clazz) {
return User.class.isAssignableFrom(clazz);
}
在此範例中,驗證器僅配置為支援驗證User類型或其子類別的物件。 isAssignableFrom()方法透過繼承驗證相容性 - 它對於User及其子類別傳回true ,對於任何其他類別類型false 。
2.2. validate(Object target, Errors errors)
另一方面, validate()方法在Spring的驗證框架中起著至關重要的作用。這是我們為驗證器支援的物件定義自訂驗證邏輯的地方。
此方法接收兩個關鍵參數:
-
Object target:此參數代表要驗證的實際物件。 Spring MVC 會自動將我們嘗試驗證的物件傳遞給此方法。 -
Errors:此參數是Errors介面的實例。它提供了向物件添加驗證錯誤的各種方法。
這是validate()方法的範例:
@Override
public void validate(Object target, Errors errors) {
User user = (User) target;
if (StringUtils.isEmpty(user.getName())) {
errors.rejectValue("name", "name.required", "Name cannot be empty");
}
}
在此範例中, validate()方法對User物件執行各種驗證,並使用針對目標欄位錯誤的rejectValue()將特定錯誤訊息新增至Errors物件。值得注意的是, rejectValue()採用三個主要參數:
-
field: 有錯誤的欄位名稱,例如“name” -
errorCode:標識錯誤的唯一代碼,例如“name.required” -
defaultMessage:如果沒有找到其他訊息,則顯示預設錯誤訊息,例如“Name cannot be empty”
3. 實作Validator
要建立驗證器,我們需要實作Validator介面。下面是一個驗證User物件的簡單驗證器的範例:
public class UserValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return User.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
User user = (User) target;
if (StringUtils.isEmpty(user.getName())) {
errors.rejectValue("name", "name.required", "Name cannot be empty");
}
if (StringUtils.isEmpty(user.getEmail())) {
errors.rejectValue("email", "email.required", "Invalid email format");
}
}
}
3.1.建立User類別
在應用驗證之前,必須定義我們要驗證的物件的結構。這是User類別的範例:
public class User {
private String name;
private String email;
// Getters and Setters
}
3.2.配置 Spring Bean
接下來,要將自訂驗證器整合到基於 Spring 的應用程式中,我們可以使用 Spring 配置類別將其註冊為應用程式上下文中的 bean。此註冊可確保驗證器在整個應用程式生命週期中可用於依賴項注入:
@Configuration
public class AppConfig implements WebMvcConfigurer{
@Bean
public UserValidator userValidator() {
return new UserValidator();
}
}
透過使用@Bean註解userValidator()方法,我們確保它傳回 Spring 在應用程式上下文中註冊為 bean 的物件。
3.3.將Validator整合到 Spring MVC 控制器中
一旦我們註冊了驗證器,我們就可以使用它來驗證 Spring MVC 控制器中的User物件。
接下來,我們建立一個UserController來處理與使用者相關的請求:
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserValidator userValidator;
@PostMapping
public ResponseEntity<?> createUser(@RequestBody User user) {
Errors errors = new BeanPropertyBindingResult(user, "user");
userValidator.validate(user, errors);
if (errors.hasErrors()) {
return ResponseEntity.badRequest().body(errors.getAllErrors());
}
// Save the user object to the database
return ResponseEntity.ok("User created successfully!");
}
}
在此範例中,我們使用 Spring 的@RestController註解來指示該控制器傳回 JSON 回應。此外,我們使用@RequestBody將傳入的 JSON 請求正文綁定到User物件。如果驗證失敗,我們將傳回 400 Bad Request 回應,其中包含包含錯誤訊息的 JSON 正文。否則,我們將傳回 200 OK 回應以及成功訊息。
4. 使用 Curl 進行測試
要使用curl測試此API,我們可以發送帶有User物件資料的JSON請求正文:
curl -X POST \
http://localhost:8080/api/users \
-H 'Content-Type: application/json' \
-d '{"name":"","email":""}'
這應該會傳回 400 Bad Request 回應,其中包含包含錯誤訊息的 JSON 正文:
[
{
"codes": [
"name.required.user.name",
"name.required.name",
"name.required.java.lang.String",
"name.required"
],
"arguments": null,
"defaultMessage": "Name cannot be empty",
"objectName": "user",
"field": "name",
"rejectedValue": "",
"bindingFailure": false,
"code": "name.required"
},
{
"codes": [
"email.required.user.email",
"email.required.email",
"email.required.java.lang.String",
"email.required"
],
"arguments": null,
"defaultMessage": "Invalid email format",
"objectName": "user",
"field": "email",
"rejectedValue": "",
"bindingFailure": false,
"code": "email.required"
}
]
如果我們發送帶有姓名和電子郵件的有效User對象,API 應返回 200 OK 回應以及成功訊息:
curl -X POST \
http://localhost:8080/api/users \
-H 'Content-Type: application/json' \
-d '{"name":"John Doe","email":"[email protected]"}'
結果,請求傳回了帶有成功訊息的回應:
"User created successfully!"
5. 驗證上下文
此外,在某些情況下,我們可能希望將額外的上下文傳遞給驗證器。 Spring 的Validator介面透過validate(Object target, Errors errors, Object… validationHints)方法支援驗證上下文。因此,要使用驗證上下文,我們可以在呼叫validate()方法時傳遞其他物件作為驗證提示。
例如,我們要根據特定場景驗證User物件:
public void validate(Object target, Errors errors, Object... validationHints) {
User user = (User) target;
if (validationHints.length > 0) {
if (validationHints[0] == "create") {
if (StringUtils.isEmpty(user.getName())) {
errors.rejectValue("name", "name.required", "Name cannot be empty");
}
if (StringUtils.isEmpty(user.getEmail())) {
errors.rejectValue("email", "email.required", "Invalid email format");
}
} else if (validationHints[0] == "update") {
// Perform update-specific validation
if (StringUtils.isEmpty(user.getName()) && StringUtils.isEmpty(user.getEmail())) {
errors.rejectValue("name", "name.or.email.required", "Name or email cannot be empty");
}
}
} else {
// Perform default validation
}
}
在此範例中, UserValidator檢查validationHints陣列以決定要使用的驗證方案。讓我們更新UserController以將UserValidator與validationHints結合使用:
@PutMapping("/{id}")
public ResponseEntity<?> updateUser(@PathVariable Long id, @RequestBody User user) {
Errors errors = new BeanPropertyBindingResult(user, "user");
userValidator.validate(user, errors, "update");
if (errors.hasErrors()) {
return ResponseEntity.badRequest().body(errors.getAllErrors());
}
// Update the user object in the database
return ResponseEntity.ok("User updated successfully!");
}
現在,讓我們發送以下curl命令,並將name和email欄位都清空:
curl -X PUT \
http://localhost:8080/api/users/1 \
-H 'Content-Type: application/json' \
-d '{"name":"","email":""}'
UserValidator回傳 400 Bad Request 回應以及錯誤訊息:
[
{
"codes": [
"name.or.email.required.user.name",
"name.or.email.required.name",
"name.or.email.required.java.lang.String",
"name.or.email.required"
],
"arguments": null,
"defaultMessage": "Name or email cannot be empty",
"objectName": "user",
"field": "name",
"rejectedValue": "",
"bindingFailure": false,
"code": "name.or.email.required"
}
]
如果我們只傳遞其中一個字段,例如name字段,則UserValidator允許更新繼續進行:
curl -X PUT \
http://localhost:8080/api/users/1 \
-H 'Content-Type: application/json' \
-d '{"name":"John Doe"}'
響應為200 OK響應,表示更新成功:
"User updated successfully!"
六,結論
在本文中,我們學習如何使用Validator介面來驗證基於 Spring 的應用程式中的物件。我們探索了Validator介面的兩種方法, supports()和validate() ,以及如何實作自訂驗證器來驗證物件。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。