欢迎你来读这篇博客,这篇博客主要是关于Validation
。
其中包括了关于我的见解和收集的知识分享。
序言
@Validated
是 Spring 提供的一个注解,用于启用方法参数的校验。在 Spring Boot 中,@Validated
通常结合 JSR-303/JSR-380
规范(例如
Hibernate Validator
)中的注解使用,比如 @NotNull
、@Size
、@Min
、@Max
等,用于对控制器、服务方法的参数进行验证,特别是处理用户输入时常见的有效性校验需求。
正文
基本用法
@Validated
可以放在类、方法上,用于校验请求对象的属性值是否符合约束。通常搭配以下三类注解一起使用:
- 字段级注解:如 @NotNull、@Size、@Email 等,放在对象的属性上。
- 分组校验:通过不同的校验组,可以实现对不同场景的校验。
- 级联校验:用于嵌套对象的校验。
常见注解
- @NotNull:字段不能为 null。
- @NotEmpty:集合、数组、字符串不能为 null 且不能为空。
- @NotBlank:字符串必须包含非空白字符。
- @Size(min=, max=):指定集合、数组、字符串的长度范围。
- @Min(value=) / @Max(value=):指定数值的最小/最大值。
- @Email:邮箱格式校验。
- @Pattern(regexp=):正则表达式校验,适用于字符串。
以下是简要示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Size;
public class UserDTO { @NotBlank(message = "用户名不能为空") @Size(min = 3, max = 20, message = "用户名长度必须在3到20之间") private String username;
@NotBlank(message = "邮箱不能为空") @Email(message = "邮箱格式不正确") private String email; }
import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController @RequestMapping("/api/users") @Validated public class UserController {
@PostMapping("/register") public String registerUser(@Valid @RequestBody UserDTO userDTO) { return "用户注册成功: " + userDTO.getUsername(); } }
|
分组校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public interface CreateGroup extends DefaultGroup {} public interface UpdateGroup extends DefaultGroup {}
public class UserDTO {
@NotBlank(groups = CreateGroup.class, message = "用户名不能为空") private String username;
@NotBlank(groups = {CreateGroup.class, UpdateGroup.class}, message = "邮箱不能为空") @Email(groups = {CreateGroup.class, UpdateGroup.class}, message = "邮箱格式不正确") private String email; @NotBlank(groups = DefaultGroup.class, message = "C/U全都会校验") private String description; }
@PostMapping("/create") public String createUser(@Validated(CreateGroup.class) @RequestBody UserDTO userDTO) { return "创建用户成功"; }
@PutMapping("/update") public String updateUser(@Validated(UpdateGroup.class) @RequestBody UserDTO userDTO) { return "更新用户成功"; }
|
自定义校验器
示例 @UniqueUsername
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*;
@Target({ ElementType.FIELD }) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = UniqueUsernameValidator.class) public @interface UniqueUsername { String message() default "用户名已存在"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext;
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
@Override public boolean isValid(String username, ConstraintValidatorContext context) { return !username.equalsIgnoreCase("existingUser"); } }
public class UserDTO { @UniqueUsername private String username;
@Email private String email; }
|
示例 @IsLeek
定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Documented @Constraint(validatedBy = IsLeekValidator.class) public @interface IsLeek {
boolean required() default true;
String message() default "此用户不是韭零后,无法开户!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
|
定义校验器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.springframework.util.StringUtils;
public class IsLeekValidator implements ConstraintValidator<IsLeek, String> {
private boolean required;
@Override public void initialize(IsLeek constraintAnnotation) { this.required = constraintAnnotation.required(); }
@Override public boolean isValid(String name, ConstraintValidatorContext constraintValidatorContext) { if (required) { return !StringUtils.isEmpty(name) && name.startsWith("新韭菜"); } return false; } }
|
参考资料
启示录
富贵岂由人,时会高志须酬。
能成功于千载者,必以近察远。