SpringBoot
支持JSR-303
, Bean
验证框架, 默认使用Hibernate validator
JSR-303 (定义校验)
常规校验
检查是否为空
- @Null: 验证对象是否为空
- @NotNull: 验证对象不为空
- @NotBlank: 验证字符串不为空, 譬如
""
," "
都会失败 - @NotEmpty: 验证对象不为
null
, 或者集合不为空
检查长度
- @Size(min=min, max=max): 验证长度支持字符串, 集合
- @Length: 字符串大小
其他
- @Email: 验证是否为邮箱地址, 为
null
则不做校验 - @Pattern: 验证字符串是否符合正则表达式
例子:
public class WorkInfoForm {
@NotNull
Long id;
@Size(min=3, max=10)
String name;
@Email
String email;
}
分组校验
不同的业务逻辑可能会有不同的验证逻辑, 譬如更新和局部字段更新, 对于上述WorkInfoForm
, 更新时id
不能为null
, 但新增时可以为nulll
JSR-303
定义了group
的概念, 每个校验注解都必须支持, 校验注解被指定一个或者多个group
, 这样只有当group
匹配才会进行校验
public class WorkInfoForm {
// 定义一个更新类
public interface Update{};
// 定义一个新增类
public interface Add{};
@NotNull(groups={Update.class})
Long id;
@Size(min=3, max=10, groups={Update.class, Add.class})
String name;
@Email(groups={Update.class, Add.class})
String email;
}
在MVC中使用(JSR-303)校验
在Controller
中只需要给方法参数加上@Validated
即可触发一次校验
@ResponseBody
@RequestMapping("/addworkinfo.html")
public void addWorkInfo(@Validated({WorkInfoForm.Add.class}) WorkInfoForm workInfo, BindingResult result) {
if(result.hasErrors()) {
List<ObjectError> list = result.getAllErrors();
FieldError error = (FieldError) list.get(0);
System.out.println(error.getObjectName() + "," + error.getField() + "," + error.getDefaultMessage());
return;
}
return;
}
@Validated({WorkInfoForm.Add.class}) WorkInfoForm workInfo
这段代码可以接受HTTP
参数并映射到WorkInfoForm
对象, 并将验证结果存放到BindingResult
对象, Validated
注解使用了校验上下文WorkInfoForm.Add.class
, 所以都按照新增的逻辑进行校验
class BindingResult{
// 验证是否通过
hasError();
// 得到所有错误信息, 通常为`FieldError`列表
getAllErrors();
}
如果Controller
参数未提供BindingResult
对象, 则SpringMVC
将会抛出异常
自定义校验
实现效果
JSR-303
允许自定义校验, 譬如在WorkInfoForm
新增一个加班时间, 效果如下
@WorkOverTime(max=2)
int workTime;
具体实现
提供了@Constraint
来说明用了什么类作为验证注解实现类, 验证注解必须要提供三个字段message
, groups
, paylaod
@Constraint(validatedBy={WorkOverTimeValidator.class})
@Documented
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface WorkOverTime {
// 创建错误信息, 支持表达式
String message() default "本周加班时长不能超过{max}小时";
// 自定义输入内容
int max() default 5;
// 验证规则分组, 如果进行分组则必须提供
Class<?>[] groups() default {};
// 验证有效负荷
Class<? extends Payload>[] payload() default {};
}
@Constraint
声明了用什么类来实现校验, 我们创建一个WorkOverTimeValidator
来做具体的校验
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class WorkOverTimeValidator implements ConstraintValidator<WorkOverTime, Integer> {
WorkOverTime work;
int max;
// 获取注解的值
public void initialize(WorkOverTime work) {
this.work = work;
this.max = work.max()
}
// 校验逻辑
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (value == null) return true;
return value < this.max;
}
}