在业务中,会涉及到很多参数校验,通常情况下,我们会使用注解在入参中进行标注。但是一些特定的业务校验注解需要我们自定义开发。
应用场景描述
业务中入参经常有开始时间
和结束时间
,需要保证结束时间 > 开始时间,下面Demo演示了如何自定义一个参数校验注解。
自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(DateValidate.List.class)
@Constraint(validatedBy = DateValidator.class)
public @interface DateValidate {
String startDateName();
String endDateName();
//作为校验注解必须属性
String message();
//作为校验注解必须属性
Class<?>[] groups() default {};
//作为校验注解必须属性
Class<? extends Payload>[] payload() default {};
//java8新增的可重复注解
@Target(TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface List{
DateValidate[] value();
}
}
定义校验方法
/**
* @Description 时间验证,依赖于Hutool工具包做时间解析,DateUtil.parse方法会自动识别一些常用格式,使用方法:在入参类上标注,可标注多个 @DateValidate(startDateName = "startTime",endDateName = "endTime",message = "开始时间不能大于结束时间")
* @Date 2022/11/1 15:58
* @Version 1.0
**/
@Slf4j
public class DateValidator implements ConstraintValidator<DateValidate,Object> {
private String startDateName;
private String endDateName;
@Override
public void initialize(DateValidate constraintAnnotation) {
this.startDateName = constraintAnnotation.startDateName();
this.endDateName = constraintAnnotation.endDateName();
}
@Override
public boolean isValid(Object object, ConstraintValidatorContext context) {
Date startDate;
Date endDate;
try {
Field fsd = object.getClass().getDeclaredField(startDateName);
fsd.setAccessible(true);
startDate = DateUtil.parse((String)fsd.get(object));
Field fed=object.getClass().getDeclaredField(endDateName);
fed.setAccessible(true);
endDate = DateUtil.parse((String)fed.get(object));
} catch (Exception e) {
throw new RuntimeException(e);
}
//如果有时间为空放过校验,让@NotNull注解去处理
if(startDate == null || endDate == null){
return true;
}
return endDate.after(startDate);
}
}
使用方式
入参中:
@Data
@DateValidate(startDateName = "startTime",endDateName = "endTime",message = "开始时间不能大于结束时间")
public class ListForm extends PageQuery {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "开始时间")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private String startTime;
@ApiModelProperty(value = "结束时间")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private String endTime;
}
Controller中:
给ListForm加入@Valid 注解
结果演示
请求结果(全局异常捕获的)
{
"code": "110104",
"data": {},
"msg": "参数错误, 开始时间不能大于结束时间"
}
拓展
在业务需求中,还有很多可以自定义的校验注解,例如手机号码校验注解,防止sql注入校验注解。开发注解校验可以减少很多重复的校验代码。