在日常开发中,我们经常会遇到各种通用的校验场景,比如字段非空校验、字段长度校验等。下面将详细介绍 Spring MVC 中的校验相关内容。
常见校验注解
注解 | 描述 |
---|---|
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素不能为 null |
@AssertTrue | 该字段只能为 true |
@AssertFalse | 该字段的值只能为 false |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(“value”) | 被注释的元素必须是一个数字,验证小数的最小值 |
@DecimalMax(“value”) | 被注释的元素必须是一个数字,验证小数的最大值 |
@Size(max, min) | 检查该字段的 size 是否在 min 和 max 之间,可以是字符串、数组、集合、Map 等 |
@Past | 被注释的元素必须是一个过去的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
@Pattern(regexp = “[abc]”) | 被注释的元素必须符合指定的正则表达式 |
@Email | 被注释的元素必须是电子邮件地址 |
@Length(max = 5, min = 1, message = “长度在 1~5”) | 检查所属的字段的长度是否在 min 和 max 之间,只能用于字符串 |
@NotEmpty | 被注释的字符串必须非空 |
@Range | 被注释的元素必须在合适的范围内 |
@NotBlank | 不能为空,检查时会将空格忽略 |
@NotEmpty | 不能为空,这里的空是指空字符串 |
下面我们来看具体的校验实现方式。
两种校验方式
1. @Validated + BindingResult
控制器校验
这种方式中,请求实体与 BindingResult
一一对应。需要添加以下依赖:
javax.validation
validation-api
2.0.1.Final
org.springframework.boot
spring-boot-starter-validation
实体类示例
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotBlank;
@Data
@ToString
public class ReqDTO {
@NotBlank(message = "param1 不能为空")
private String param1;
@NotBlank(message = "param2 不能为空")
private String param2;
@NotBlank(message = "param3 不能为空")
private String param3;
}
控制器示例
@RestController
public class MyController {
@PostMapping("/param1")
public String param1(@Validated @RequestBody ReqDTO reqDTO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
assert fieldError != null;
return fieldError.getDefaultMessage();
}
return "success";
}
}
2. 自定义 Validator
校验工具类
此方式不局限于控制器层,可在任何地方使用。
工具类代码
@Component
public class ParamCheckUtil {
private static Validator validator;
@Autowired
private Validator injectValidator;
@PostConstruct
public void preInit() {
validator = injectValidator;
}
public static T> String checkByGroupsGetOneMessage(T t, Class>... groups) {
if (t == null) {
return null;
}
SetConstraintViolationT>> validate = validator.validate(t, groups);
if (validate.size() == 0) {
return null;
}
return validate.stream().findFirst().get().getMessage();
}
public static T> String checkByGroupsGetAllMessage(T t, Class>... groups) {
if (t == null) {
return null;
}
SetConstraintViolationT>> validate = validator.validate(t, groups);
if (validate.size() == 0) {
return null;
}
ListString> msgList = new ArrayList();
validate.forEach(cv -> msgList.add(cv.getMessage()));
return String.join(";", msgList);
}
}
应用示例
@RestController
public class MyController {
@PostMapping("/param2")
public String param2(@RequestBody ReqDTO reqDTO) {
String message = ParamCheckUtil.checkByGroupsGetAllMessage(reqDTO);
if (message != null) {
return message;
}
return "success";
}
}
其他扩展校验 - 分组校验
当一个实体类应用于多个场景的请求入参,且入参要求不同时,我们可以给校验属性添加分组,默认分组是 Default
。
实体类示例
@Data
@ToString
public class GroupReqDTO {
@NotBlank(message = "param1 不能为空")
private String param1;
@NotBlank(message = "param2 不能为空", groups = A.class)
private String param2;
@NotBlank(message = "param3 不能为空", groups = B.class)
private String param3;
public interface A {}
public interface B {}
}
控制器示例
@RestController
public class MyController {
@PostMapping("/param4")
public String param4(@Validated({GroupReqDTO.A.class}) @RequestBody GroupReqDTO reqDTO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
assert fieldError != null;
return fieldError.getDefaultMessage();
}
return "success";
}
}
通过以上内容,我们全面了解了 Spring MVC 中的校验机制,包括常见注解、两种校验方式以及分组校验的使用方法。