Spring Validator接口提供了一种灵活且可自定义的方法来验证对象。在本文中,我们学习如何使用Validator接口在基于 Spring 的应用程序中验证对象。我们探索了Validator接口的两种方法supports()和verify(),以及如何实现自定义验证器来验证对象。
什么是Spring Validator接口
Validator接口是Spring 框架的一部分,它提供了一种验证对象的方法。
它是一个简单的接口,定义了两个方法,supports()和verify()。这两个方法用于确定验证器是否可以验证对象并执行验证逻辑。
支持(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。
验证(对象目标,错误错误)
另一方面,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对象执行各种验证,并使用rejectionValue()将特定错误消息添加到Errors对象以识别目标字段错误。值得注意的是,rejectValue()有三个主要参数:
- field:出现错误的字段名称,例如“ name ”
- errorCode:标识错误的唯一代码,例如“ name.required ”
- defaultMessage:如果未找到其他消息,则显示默认错误消息,例如“名称不能为空”
实现验证器
要创建验证器,我们需要实现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"); } } }
|
创建用户类
在应用验证之前,必须定义我们要验证的对象的结构。以下是User类的一个示例:
public class User { private String name; private String email; // Getters and Setters }
|
配置 Spring Bean
接下来,为了将自定义验证器集成到基于 Spring 的应用程序中,我们可以使用 Spring 配置类将其注册为应用程序上下文中的 bean。此注册可确保验证器在整个应用程序生命周期内可用于依赖项注入:
@Configuration public class AppConfig implements WebMvcConfigurer{ @Bean public UserValidator userValidator() { return new UserValidator(); } }
|
通过用@Bean注释userValidator()方法,我们确保它返回 Spring 在应用程序上下文中注册为 bean 的对象。
在 Spring MVC 控制器中集成验证器
一旦我们注册了验证器,我们就可以使用它来验证Spring MVC 控制器中的用户对象。
接下来我们创建一个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 响应,其中包含成功消息。
使用 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" } ]
|
如果我们发送一个带有姓名和电子邮件的有效用户对象,API 应该返回 200 OK 响应以及成功消息:
curl -X POST \ http://localhost:8080/api/users \ -H 'Content-Type: application/json' \ -d '{"name":"John Doe","email":"johndoe@example.com"}'
|
结果,请求返回了带有成功消息的响应:
"User created successfully!"
|
验证上下文
此外,在某些情况下,我们可能希望将其他上下文传递给验证器。Spring的Validator接口通过validate(Object target, Errors errors, Object…validationHints)方法支持验证上下文。因此,要使用验证上下文,我们可以在调用validate()方法时传递其他对象作为验证提示。
例如,我们想根据特定场景验证用户对象:
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以使用带有validationHints的UserValidator:
@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命令,其中名称和电子邮件字段均为空:
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" } ]
|
如果我们只传递其中一个字段,例如名称字段,那么UserValidator允许更新继续:
curl -X PUT \ http://localhost:8080/api/users/1 \ -H 'Content-Type: application/json' \ -d '{"name":"John Doe"}'
|
响应是200 OK响应,表示更新成功:
"User updated successfully!"