https://blog.csdn.net/qq_21187515/article/details/109673109
背景
项目中需要根据业务,校验导入excel的每个字段。
javax.validation 中注解是比较强大的,可是不满足业务需求。比如针对几个字段进行业务校验或者针对大量的字段,自定义校验器就派上用场。
于是需要自定义校验器。
解决 & 实现
1.校验annotation(注解)
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = Validator.class)//指定校验器
public @interface ValidxxxImport {
ValidxxxEnum type();
String message() default "";
//groups 和 payload两个必填项
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2.类型枚举
@Getter
@AllArgsConstructor
public enum ValidxxxImportEnum {
NAME,
AGE,
PHONE,
}
对于不同类型有不同校验方法
3.校验器(关键)
@Slf4j
@Component
public class xxxImportValidator implements ConstraintValidator<ValidxxxImport, String> {
private ValidxxxImport validxxxImport;
private ValidxxxImportEnum validxxxImportEnum;
@Override
public void initialize(ValidxxxImport constraintAnnotation) {
this.validxxxImport = constraintAnnotation;
this.validxxxImportEnum = constraintAnnotation.type();
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
if (ValidxxxImportEnum.NAME.equals(validxxxImportEnum)) {
//业务校验方法1
} else if (ValidxxxImportEnum.PHONE.equals(validxxxImportEnum)) {
//业务校验方法2
}
return false;
}
}
4.需校验req
@Data
@ApiModel(value = "导入dto")
public class ExcelDto implements Serializable {
private static final long serialVersionUID = 1L;
@ValidPlanRuleImport(type = ValidPlanRuleImportEnum.NAME)
private String field1;
@ValidPlanRuleImport(type = ValidPlanRuleImportEnum.PHONE)
private String field2;
@ValidPlanRuleImport(type = ValidPlanRuleImportEnum.AGE)
private String field3;
}
5.业务服务实现类
import javax.validation.Validator;
import javax.validation.groups.Default;
@Service
public class xxxService{
@Autowired
private Validator validator;
for (int i = 0; i < list.size(); i++) {
ExcelDto dto = list.get(i);
//这里默认使用javax.validation.groups.Default分组
Set<ConstraintViolation<ExcelDto>> set = validator.validate(dto, Default.class);
if (!CollectionUtils.isEmpty(set)) {
//说明有违反校验规则信息
//校验没通过,可以打印错误信息,以及相关字段等
for (ConstraintViolation<PlanRuleExcelDto> result : set) {
log.info("校验失败: property[{}] value[{}]", result.getPropertyPath(), result.getInvalidValue());
}
}
}
输出日志
校验失败: property[no1] value[elit]
校验失败: property[no2] value[dolore aliquip]
校验失败: property[no3] value[pariatur commodo]