SpringBoot参数校验之@Valid的使用详解
在Spring Boot中,参数校验是非常重要的一环,在实际开发中,我们经常会遇到需要对用户提交的数据进行校验的场景,比如注册时,我们需要校验用户名、密码、邮箱格式等数据是否符合要求。这时,我们就可以通过使用Spring Boot提供的参数校验功能来实现。
Spring Boot提供了一个非常方便的参数校验工具——Java Bean Validation,通过注解、API等方式可以方便地对Java Bean对象属性的有效性进行校验。其中,最为常用的注解就是@Valid注解。
@Valid注解的作用
@Valid注解表示需要对被注解的对象进行校验,通常用在Controller层的方法参数上。
如何使用@Valid注解实现参数校验
在使用@Valid注解进行参数校验之前,需要先引入相关依赖,依赖的配置如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
当引入了上述的依赖后,就可以在Controller层的方法参数上使用@Valid注解进行参数校验了。例如:
@PostMapping("/register")
public String register(@Valid User user) {
// do something
}
在上述的例子中,@Valid注解被用来校验User对象,如果User对象中的某些属性不合法,那么在校验时就会抛出MethodArgumentNotValidException异常。
同时在实际使用中,还需要在User对象的相应属性上加上校验注解,例如:@NotNull、@Size等。示例:
public class User {
@NotNull(message = "用户名不能为空")
private String userName;
@NotNull(message = "密码不能为空")
@Size(min = 6, max = 16, message = "密码长度必须在6~16之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
// getter/setter方法...
}
在上述的例子中,@NotNull注解表示userName和password属性的值不能为空,@Size注解表示password属性的值长度必须在6~16之间,@Email注解表示email属性的值必须是一个符合邮箱格式要求的字符串。
多参数校验
在实际开发中,我们可能需要校验多个参数,此时可以使用嵌套对象的方式来实现。例如:
public class LoginRequest {
@NotNull(message = "用户名不能为空")
private String userName;
@NotNull(message = "密码不能为空")
@Size(min = 6, max = 16, message = "密码长度必须在6~16之间")
private String password;
// getter/setter方法...
}
@PostMapping("/login")
public String login(@Valid LoginRequest loginRequest) {
// do something
}
在上述的例子中,LoginRequest对象中包含了userName和password属性,在方法参数上使用@Valid注解表示需要对LoginRequest对象进行校验,并在LoginRequest类的相应属性上再加上其他的校验注解即可。
自定义校验
在实际开发中,我们可能会遇到一些特定的校验需求,此时可以使用自定义校验注解来实现。自定义校验注解十分灵活,能够实现各种各样的校验需求。例如,我们可以自定义一个注解,来表示一个字符串必须是一个由字母、数字和下划线组成的字符串,示例:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {UserNameValidator.class})
public @interface UserName {
String message() default "用户名必须是字母、数字、下划线";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class UserNameValidator implements ConstraintValidator<UserName, String> {
@Override
public void initialize(UserName constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
return value.matches("^[A-Za-z0-9_]+$");
}
}
在上述的例子中,自定义了一个@UserName注解,表示一个字符串必须是一个由字母、数字和下划线组成的字符串。在定义了@UserName注解之后,需要编写一个UserNameValidator类,来实现具体的校验逻辑。
在Controller层中定义全局异常处理器
在使用参数校验时,如果某个参数不合法,就会抛出MethodArgumentNotValidException异常,为了更好地处理这个异常,可以在Controller层中定义一个全局异常处理器。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
StringBuilder builder = new StringBuilder();
bindingResult.getFieldErrors().forEach(fieldError -> builder.append(fieldError.getDefaultMessage()).append("; "));
ErrorResponse response = new ErrorResponse("参数校验失败:" + builder.toString());
return ResponseEntity.badRequest().body(response);
}
}
在上述的例子中,定义了一个全局异常处理器GlobalExceptionHandler,当抛出MethodArgumentNotValidException异常时,会进入handleMethodArgumentNotValidException方法进行处理。在该方法中,首先获取BindingResult对象,然后获取每一个FieldError对象并拼接错误信息,最后返回一个ErrorResponse对象,表示参数校验失败。
示例
下面我们通过一个完整的示例来演示如何使用@Valid注解实现参数校验。该示例是实现一个注册功能,包含一个注册页面和一个注册接口。
注册页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<h1>用户注册</h1>
<form action="/register" method="post">
用户名:<input type="text" name="userName"><br>
密码:<input type="password" name="password"><br>
邮箱:<input type="email" name="email"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
注册接口代码
@PostMapping("/register")
public ResponseEntity<SuccessResponse> register(@Valid User user) {
userService.register(user.getUserName(), user.getPassword(), user.getEmail());
return ResponseEntity.ok().body(new SuccessResponse("注册成功"));
}
在该代码中,@Valid注解被用来校验User对象的三个属性:userName、password和email,如果其中任何一个属性的值不合法,就会抛出MethodArgumentNotValidException异常。在实际开发中,我们需要在User类中添加对应的注解,示例:
public class User {
@NotNull(message = "用户名不能为空")
private String userName;
@NotNull(message = "密码不能为空")
@Size(min = 6, max = 16, message = "密码长度必须在6~16之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
// getter/setter方法...
}
在该代码中,@NotNull注解表示userName和password属性的值不能为空,@Size注解表示password属性的值长度必须在6~16之间,@Email注解表示email属性的值必须是一个符合邮箱格式要求的字符串。
同时,在Controller层中,我们通过定义一个全局异常处理器GlobalExceptionHandler,来对参数校验时抛出的异常进行统一处理,示例:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
StringBuilder builder = new StringBuilder();
// 获取每一个错误消息,拼接成一个字符串
bindingResult.getFieldErrors().forEach(fieldError -> builder.append(fieldError.getDefaultMessage()).append("; "));
ErrorResponse response = new ErrorResponse("参数校验失败:" + builder.toString());
return ResponseEntity.badRequest().body(response);
}
}
在该代码中,我们通过@ControllerAdvice注解来标记该类为全局异常处理器,将handleMethodArgumentNotValidException方法标记为对MethodArgumentNotValidException异常进行处理的方法。在该方法中,我们首先获取BindingResult对象,然后获取每一个FieldError对象并拼接错误信息,最后返回一个ErrorResponse对象,表示参数校验失败。
在运行程序之后,访问注册页面,输入正确的用户名、密码和邮箱,就可以看到注册成功的信息。如果输入不合法的数据,比如用户没有输入用户名,或者输入的密码长度小于6等,就会看到参数校验失败的提示信息。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot参数校验之@Valid的使用详解 - Python技术站