一般自定义校验注解需要已下三步:
1.编写校验注解 即类似@NotEmpty
2.编写自定义校验的逻辑实体类,这个类必须实现ConstraintValidator
这个接口,这样才可以被注解用来校验。
3.编写具体的校验逻辑。
我们可以先观察下@NotEmpty 注解:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.hibernate.validator.constraints;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraintvalidation.SupportedValidationTarget;
import javax.validation.constraintvalidation.ValidationTarget;
@Documented
@Constraint(
validatedBy = {}
)
@SupportedValidationTarget({ValidationTarget.ANNOTATED_ELEMENT})
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
@NotNull
@Size(
min = 1
)
public @interface NotEmpty {
String message() default "{org.hibernate.validator.constraints.NotEmpty.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface List {
NotEmpty[] value();
}
}
我们编写的自定义注解类,也必须有message、groups、payload.
package com.zzidc.web.validator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
* @Description //TODO
* @Date 2019/3/29 17:22
* @Param
* @return
**/
//注解是指定当前自定义注解可以使用在哪些地方,这里仅仅让他可以使用在方法上和属性上;
@Target({ElementType.METHOD,ElementType.FIELD})
//指定当前注解保留到运行时;
@Retention(RetentionPolicy.RUNTIME)
//指定了当前注解使用哪个类来进行校验。
@Constraint(validatedBy = IdCardValidator.class) //
public @interface IsIdCard {
String message();
// default 关键字 接口中被default修饰的方法,在类实现这个接口时不必必须实现这个方法
Class<?>[] groups() default { };
// Class<?> 表示不确定的java类型
// Class<T> 表示java类型
// Class<K,V> 分别代表java键值中的key value
// Class<E> 代表Element
Class<? extends Payload>[] payload() default {};
}
编写校验注解的逻辑类,该类必须实现ConstraintValidator:
package com.zzidc.web.validator;
import com.zzidc.web.service.IdCardValidatorService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* @ClassName IdCardValidator
* @Description 校验注解的校验逻辑
* @Date 2019/3/29 17:23
**/
public class IdCardValidator implements ConstraintValidator<IsIdCard,String>{
@Autowired
private IdCardValidatorService idCardValidatorService;
/*
* @Description 校验前的初始化工作
* @Date 2019/3/29 17:27
* @Param [isIdCard]
* @return void
**/
@Override
public void initialize(IsIdCard isIdCard) {
String message = isIdCard.message();
System.out.println("自定义的message信息是:".concat(message));
}
/*
* @Description 具体的校验逻辑
* @Date 2019/3/29 17:29
* @Param [s, constraintValidatorContext]
* @return boolean
**/
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return idCardValidatorService.volid(s);
}
}
在这里我们将具体校验逻辑抽出来,抽成一个service:
package com.zzidc.web.service;
/**
* @ClassName IdCardValidatorService
* @Description TODO
* @Date 2019/3/29 17:34
**/
public interface IdCardValidatorService {
boolean volid(String value);
}
package com.zzidc.web.service.impl;
import com.zzidc.web.service.IdCardValidatorService;
import com.zzidc.web.utils.IdCardUtils;
import org.springframework.stereotype.Service;
/**
* @ClassName IdCardValidatorServiceImpl
* @Description TODO
* @Date 2019/3/29 17:35
**/
@Service
public class IdCardValidatorServiceImpl implements IdCardValidatorService {
@Override
public boolean volid(String value) {
return IdCardUtils.isValidIdCard(value);
}
}
工具类:
package com.zzidc.web.utils;
import org.apache.commons.lang3.StringUtils;
/**
* @ClassName IdCardUtils
* @Description TODO
* @Date 2019/3/29 17:37
**/
public class IdCardUtils {
public static boolean isValidIdCard(String value){
String regex = "^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$";
if (StringUtils.isBlank(value)) {
return false;
}
return value.matches(regex);
}
}