说明
spring validate 中自带的校验注解往往不能满足我们的业务需求,此时需要自定义注解作用在实体类的属性上,用来进行参数的校验。
创建自定义校验
创建自定义校验注解
说明
在此创建一个注解,用于校验使用此注解的实体属性值是否属于多个值中的其中一个。类似于java中的 contains() 方法。
创建注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 校验值是否在指定值中
*/
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
//通过ContainsValidator类实现注解的相关校验操作
@Constraint(validatedBy = ContainsValidator.class)
@Documented
public @interface ContainsValidata {
String message() default "字段值不正确";
String[] values() default {}; // 指定值
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
//指定多个时使用
@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface List {
ContainsValidata[] value();
}
}
创建注解对应的校验逻辑实现类
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class ContainsValidator implements ConstraintValidator<ContainsValidata,String> {
// 全局变量存放值集合
private List<String> values = new ArrayList<>();
// 注解初始化时执行
@Override
public void initialize(ContainsValidata constraintAnnotation) {
// 获取注解中的值
String[] strList = constraintAnnotation.values();
// 赋值给全局变量
values = Arrays.stream(strList).collect(Collectors.toList());
}
// 自定义的校验规则
@Override
public boolean isValid(String o, ConstraintValidatorContext constraintValidatorContext) {
// o 为实体属性的值
// 判断值是否属于集合中的元素,true 检验通过,false校验不通过
return values.contains(o);
}
}
自定义注解的使用
在实体类中有以下属性
@Data
@ToString
@ApiModel(description = "分页数据")
public class BasePageVo {
@ApiModelProperty(value = "当前页码", dataType = "String")
private String pageNumber = "1";
@ApiModelProperty(value = "每页数量", dataType = "String")
private String pageSize = "10";
@ApiModelProperty(value = "排序方式", dataType = "String")
//使用自定义注解 ,且该属性值只能为"desc","asc"之一
@ContainsValidata(message = "排序方式不正确",values = {"desc","asc"} )
private String order = "desc";
@ApiModelProperty(value = "排序字段,多个用逗号分割", dataType = "String")
private String orderBy = "id";
}
使用公共异常处理器处理校验不通过的结果
校验不同过时候,将校验不通过的提示信息返回给前端,创建公共异常处理,如下:
@ControllerAdvice
@Slf4j
@ResponseBody
public class ExceptionControllerHandler {
/**
* 说明: 接口实体参数校验不通过
* @author zhangxiaosan
* @create 2022/2/23
* @param
* @return
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public void methodArgumentNotValidExceptionHandler(HttpServletResponse response,MethodArgumentNotValidException e) throws IOException {
response.setContentType("application/json");//设置相应格式
response.setContentType("text/html;charset=utf-8");//设置相应格式
response.setCharacterEncoding("UTF-8");
// 获取到所有异常信息,put 到 mapList中去
List<String> errorList = e.getBindingResult()
.getFieldErrors()
.stream()
.map(m -> m.getDefaultMessage())
.collect(Collectors.toList());
response.getWriter().println(Response.failParam(errorList,"参数校验不通过"));
}
}