JSR303校验的使用
1.给bean的属性添加校验注解并自定义校验提示信息
更多校验注解参考javax.validation.constraints包;
BrandEntity.java
@NotBlank(message = "不能为空")
private String name;
// 品牌logo地址
@URL(message = "logo必须是一个合法的url地址")
private String logo;
//使用正则表达式定义校验规则
@Pattern(regexp = "^[a-zA-Z]$",message = "检索首字母不能为空")
@NotEmpty
//最小值为0
@Min(value = 0,message = "排序必须大于等于0")
private Integer sort;
2.@Valid标注在参数上告诉springmvc开启校验功能
BrandController.java
@RequestMapping("/save")
// @RequiresPermissions("product:brand:save")
public R save(@Valid @RequestBody BrandEntity brand){
brandService.save(brand);
return R.ok();
}
3.在被校验的bean后紧跟一个BindingResult ,就可以获取校验的结果(这里的R是我业务统一要求的返回规范)
@RequestMapping("/save")
// @RequiresPermissions("product:brand:save")
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
HashMap<String, String> stringMap = new HashMap<>();
//获取校验错误结果
if(result.hasErrors()){
result.getFieldErrors().forEach((error)->{
//获取并封装校验错误属性与错误信息
stringMap.put(error.getField(),error.getDefaultMessage());
});
return R.error(400,"提交数据不合法").put("data",stringMap);
}else {
brandService.save(brand);
return R.ok();
}
当然在实际项目中我们不建议以上的写法,代码的复用性极低,推荐使用springboot的统一异常处理机制
使用枚举在公共模块中创建异常状态码枚举
package com.walkwind.common.exception;
/**
* @Author walkwind
* @Description 错误状态码
* @Date 2020-5-10-18:21
**/
public enum BizCodeEnum {
UNKONW_EXCEPTION(10000, "系统位置错误"),
VALID_EXCEPTION(10001, "参数格式校验失败");
private Integer code;
private String msg;
BizCodeEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
//省略getter/setter方法..
}
创建exception类使用@ControllerAdvice用来处理请求
@ControllerAdvice //全局异常处理,全局数据绑定,全局数据预处理
public class WwmallProductExceptionCcontrollerAdvice {
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handlerVaildException(MethodArgumentNotValidException e) {
HashMap<String, String> stringMap = new HashMap<>();
//获取校验错误结果
e.getBindingResult().getFieldErrors().forEach((error) -> {
//获取并封装校验错误属性与错误信息
stringMap.put(error.getField(), error.getDefaultMessage());
});
return R.error(BizCodeEnum.VALID_EXCEPTION.getCode(),BizCodeEnum.VALID_EXCEPTION.getMsg()).put("data", stringMap);
}
}
这样话我们在数据校验层就不必每次都捕捉数据校验异常,有异常直接throw我们的异常处理器会自动捕捉
public R save(@Valid @RequestBody BrandEntity brand){
brandService.save(brand);
return R.ok();
}
JSR303分组校验
我们在新增时和修改时想要校验的字段,校验规则一般是不同的,例:新增时需要校验排序字段是否为空,而我们修改时就不会涉及到排序字段的修改,所以我们使用分组校验
在common中新建两个接口AddGroup,UpdateGroup这两个接口只起到标识作用,不需要有任何实现。
使用group属性给校验注解标注什么情况下需要校验,所有被校验的属性必须全部指定group
@NotBlank(message = "不能为空" ,groups = {AddGroup.class, UpdateGroup.class})
private String name;
@NotEmpty(message = "不能为空",groups = {AddGroup.class, UpdateGroup.class})
@Min(value = 0,message = "排序必须大于等于0",groups = {AddGroup.class})
private Integer sort;
使用@validated({gruop.class})标注在被校验的参数上即可
public R save(@Validated(AddGroup.class) @RequestBody BrandEntity brand){
brandService.save(brand);
return R.ok();
}
注: 没有指定分组的校验注解,分组校验时不生效
自定义校验规则
需求:校验show_status的值只能为0或1
自定义校验注解
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class })
public @interface ListValue {
//校验错误默认信息读取位置
String message() default "{com.walkwind.common.valid.ListValue.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
int[] values() default { };
}
自定义校验器
引入依赖
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
在resources文件夹下新建文件ValidationMessages.properties设置默认message
com.walkwind.common.valid.ListValue.message=必须提交指定值
校验器
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {
private Set<Integer> set = new HashSet<>();
//初始化方法
@Override
public void initialize(ListValue constraintAnnotation) {
int[] values = constraintAnnotation.values();
for (int value:values) {
set.add(value);
}
}
@Override
//校验方法
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
return set.contains(integer);
}
}
自定义校验注解关联自定义校验器
@Constraint(validatedBy = {ListValueConstraintValidator.class })
使用自定义注解
@ListValue(values = 0,groups = {AddGroup.class,UpdateGroup.class})
private Integer showStatus