在日常开发中,我们经常会遇到各种通用的校验场景,比如字段非空校验、字段长度校验等。下面将详细介绍 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.validationvalidation-api2.0.1.Finalorg.springframework.bootspring-boot-starter-validation
实体类示例
import lombok.Data;import lombok.ToString;import javax.validation.constraints.NotBlank;@Data@ToStringpublic class ReqDTO {@NotBlank(message = "param1 不能为空")private String param1;@NotBlank(message = "param2 不能为空")private String param2;@NotBlank(message = "param3 不能为空")private String param3;}
控制器示例
@RestControllerpublic 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 校验工具类
此方式不局限于控制器层,可在任何地方使用。
工具类代码
@Componentpublic class ParamCheckUtil {private static Validator validator;@Autowiredprivate Validator injectValidator;@PostConstructpublic 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);}}
应用示例
@RestControllerpublic class MyController {@PostMapping("/param2")public String param2(@RequestBody ReqDTO reqDTO) {String message = ParamCheckUtil.checkByGroupsGetAllMessage(reqDTO);if (message != null) {return message;}return "success";}}
其他扩展校验 - 分组校验
当一个实体类应用于多个场景的请求入参,且入参要求不同时,我们可以给校验属性添加分组,默认分组是 Default。
实体类示例
@Data@ToStringpublic 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 {}}
控制器示例
@RestControllerpublic 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 中的校验机制,包括常见注解、两种校验方式以及分组校验的使用方法。
