1.什么是JSR
JSR是Java Specification Requests的缩写,意思是Java 规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
2.什么是JSR303
JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
3.快速使用
3.1 给bean添加校验注解
该注解被定义在 javax.validation.constraints 包下面
@NotNull private String name;
自定义校验规则
@Pattern(regexp = "/^[a-zA-Z]$/",message = "检索首字母必须是一个字母") private String productUnit;
3.2 开启校验
在需要校验的接口添加注解@Valid,例如:
3.3 调用接口
调用接口的时候我们可以看到校验规则已生效,校验错误以后就会有默认的响应
3.4 自定义返回结果
上述校验失败后的返回结果不满足我们统一返回给前端的样式,所以我们现在需要给校验失败重新返回信息,给校验的bean后紧一个 BindingResult ,就可以获取到校验的结果
完整写法如下:
@RequestMapping("/update") public R update(@Valid @RequestBody CategoryEntity category, BindingResult result) { if (result.hasErrors()) { Map<String, String> map = new HashMap<>(); //获取校验的错误结果 List<FieldError> fieldErrors = result.getFieldErrors(); fieldErrors.forEach(fieldError -> { String message = fieldError.getDefaultMessage();//错误提示消息 String field = fieldError.getField(); //获取错误的属性名 map.put(field, message); }); return R.error(400, "提交的数据不合法").put("map", map); } categoryService.updateById(category); return R.ok(); }
再次响应结果如下:
4.分组校验
4.1 使用场景
同一个字段有在不同的场景应该有不同的校验规则,比如id在添加的时候必须为空,而在修改的时候不能为空
这时我们可以对id进行分租校验,如下:
@NotNull(message = "修改不能为空",groups = UpdateGroup.class) @Null(message = "新增必须为空",groups = AddGroup.class) @TableId private Long catId;
4.2 开启校验
给校验注解标注什么情况下进行校验
@RequestMapping("/update") public R update(@Validated({UpdateGroup.class}) @RequestBody CategoryEntity category) { categoryService.updateById(category); return R.ok(); }
注:默认没有指定分组的校验注解在分组校验情况下不生效。
5.自定义校验
5.1 编写自定义校验注解
Constraint中指定校验规则类
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Constraint( validatedBy = {ListValueConstraintValidator.class} ) public @interface ListValue { String message() default "{com.gh.common.valid.ListValue.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; int[] vals() default { }; }
5.2 编写自定义校验规则器
创建校验规则类,实现ConstraintValidator接口,其中两个参数的含义分别是:第一个代表自定义的注解,第二个代表被校验属性的类型
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> { private Set<Integer> set = new HashSet<>(); //初始化,接收到注解里的值 @Override public void initialize(ListValue constraintAnnotation) { int[] vals = constraintAnnotation.vals(); if (vals != null && vals.length > 0) { for (int val : vals) { set.add(val); } } } //判断是否校验成功 @Override public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) { return set.contains(value); } }
5.3 自定义校验失败消息
在resources目录下新建一个文件ValidationMessages.properties,在里面指定校验失败的消息
com.gh.common.valid.ListValue.message=必须提交指定的值
而此消息在自定义注解的message的default中指定
5.4 使用自定义注解
这里指定传入的值必须为1或0,否则会校验失败
@ListValue(vals = {0, 1}, groups = UpdateGroup.class) @TableLogic(value = "1", delval = "0") private Integer showStatus;
5.5 校验结果
当我们传入的值为3时会触发