一、简介
有时候在做项目的过程中会发现Hibernate Validation提供的验证规则并不能百分百的复合业务需要,就如,在插入数据库时要保证插入进去的某个属性的ID必须要唯一,不能重复插入,类似于表单不能重复提交,,在这个时候,我们就得扩展Validation来实现自己的业务,具体步骤如下:
1、首先定义一个注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* @version V1.0
* @Author fendo
* @ClassName MobileCheck
* @PackageName
* @Description 数据插入ID唯一校验
* @Data 2017-09-21 10:47
**/
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
//指定验证器
@Constraint(validatedBy = CheckValidator.class)
@Documented
public @interface InsertCheck {
//默认错误消息
String message() default "{forbidden.word}";
//查询的表名
String tableName() default "";
String cloumn() default "";
String sql() default "";
//分组
Class<?>[] groups() default { };
//负载
Class<? extends Payload>[] payload() default { };
//指定多个时使用
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Documented
@interface List {
InsertCheck[] value();
}
}
2、定义一个类实现ConstraintValidator
import com.gz.medicine.common.util.JuheUtil;
import com.gz.medicine.common.util.RegexUtils;
import com.gz.medicine.common.util.SimpleResult;
import com.gz.medicine.common.util.TimeUtil;
import com.gz.medicine.gzyun.health.mapper.HealthyOrderMapper;
import org.apache.commons.collections.map.HashedMap;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* @version V1.0
* @Author fendo
* @ClassName MobileCheck
* @PackageName
* @Description 扩展Validator
* @Data 2017-09-21 10:47
**/
public class CheckValidator implements ConstraintValidator<Annotation, Object> {
@Autowired
HealthyOrderMapper healthyordermapper; //数据库操作Mapper
public static final Logger LOGGER = Logger.getLogger(CheckValidator.class);
public static final String DATE_CHECK ="((^((1[8-9]\\d{2})|([2-9]\\d{3}))([-\\/\\._])(10|12|0?[13578])([-\\/\\._])(3[01]|[12][0-9]|0?[1-9])$)|(^((1[8-9]\\d{2})|([2-9]\\d{3}))([-\\/\\._])(11|0?[469])([-\\/\\._])(30|[12][0-9]|0?[1-9])$)|(^((1[8-9]\\d{2})|([2-9]\\d{3}))([-\\/\\._])(0?2)([-\\/\\._])(2[0-8]|1[0-9]|0?[1-9])$)|(^([2468][048]00)([-\\/\\._])(0?2)([-\\/\\._])(29)$)|(^([3579][26]00)([-\\/\\._])(0?2)([-\\/\\._])(29)$)|(^([1][89][0][48])([-\\/\\._])(0?2)([-\\/\\._])(29)$)|(^([2-9][0-9][0][48])([-\\/\\._])(0?2)([-\\/\\._])(29)$)|(^([1][89][2468][048])([-\\/\\._])(0?2)([-\\/\\._])(29)$)|(^([2-9][0-9][2468][048])([-\\/\\._])(0?2)([-\\/\\._])(29)$)|(^([1][89][13579][26])([-\\/\\._])(0?2)([-\\/\\._])(29)$)|(^([2-9][0-9][13579][26])([-\\/\\._])(0?2)([-\\/\\._])(29)$))";
public static final String TIME_CHECK="^([0-1]?[0-9]|2[0-3]):([0-5][0-9])";
public static final String YYYYMMHHDDMI="^(\\d{4})-(0\\d{1}|1[0-2])-(0\\d{1}|[12]\\d{1}|3[01]) (0\\d{1}|1\\d{1}|2[0-3]):([0-5]\\d{1})$";
private String value;
private int annotationType;
@Override
public void initialize(Annotation annotation) {
if (annotation instanceof InsertCheck) {
annotationType = 0;
InsertCheck ak = (InsertCheck) annotation;
this.value = ak.sql();
}
if (annotation instanceof DateCheck) {
annotationType = 1;
DateCheck dk = (DateCheck) annotation;
this.value = dk.type();
}
if (annotation instanceof IdCardCheck) {
annotationType = 2;
IdCardCheck ik = (IdCardCheck) annotation;
}
if (annotation instanceof MobileCheck) {
annotationType = 3;
MobileCheck ik = (MobileCheck) annotation;
}
}
public static void main(String[] args) {
System.out.println(Pattern.matches("","2017-12-32 09:54"));
}
@Override
public boolean isValid(Object ot, ConstraintValidatorContext constraintValidatorContext) {
boolean re = false;
try {
switch (annotationType) {
case 0: {
try {
String key = this.value.substring(this.value.indexOf("{") + 1, this.value.indexOf("}"));
Map<String, Object> mp = new HashedMap();
mp.put("sql", this.value);
mp.put(key, ot);
List<Map<String, Object>> li = healthyordermapper.exuSql(mp);
System.out.println(li.size());
if (li != null && li.size() == 0) {
re = true;
}
} catch (Exception e) {
e.printStackTrace();
;
}
break;
}
case 1: {
try {
if("YYYY-MM-DD".equals(this.value)){
re =Pattern.matches(DATE_CHECK, (String) ot);
}
if("HH:MI".equals(this.value)){
re =Pattern.matches(TIME_CHECK, (String) ot);
}
if("YYYY-MM-DD HH:MI".equals(this.value)){
re =Pattern.matches(YYYYMMHHDDMI, (String) ot);
}
} catch (Exception e) {
e.printStackTrace();
;
}
break;
}
case 2: {
try {
SimpleResult sr = JuheUtil.getIdcardMsg((String) ot);
String code = (String) sr.get("code");
if ("000".equals(code)) {
re = true;
}
} catch (Exception e) {
}
break;
}
case 3:{
re = RegexUtils.isMobile((String) ot);
break;
}
}
} catch (Exception e) {
LOGGER.error("校验异常:" + e.getMessage(), e);
}
return re;
}
}
3、使用方式
/**
* 出生日期
*/
@DateCheck(type="YYYY-MM-DD",message="请输入正确的出生日期!!!!")
@NotEmpty(message="出生日期不能为空!")
String usrbirth;
/**
* 手机号码
*/
@NotEmpty(message="手机号码不能为空!")
@MobileCheck(message="请输入正确的手机号!")
String usrphone;
4、其他一些验证规则
4.1 时间验证
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @version V1.0
* @Author fendo
* @ClassName MobileCheck
* @PackageName
* @Description 时间验证
* @Data 2017-09-21 10:47
**/
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
//指定验证器
@Constraint(validatedBy = CheckValidator.class)
@Documented
public @interface DateCheck {
//默认错误消息
String message() default "YYYY-MM-DD";
//查询的表名
String type() default "YYYY-MM-DD";
//分组
Class<?>[] groups() default { };
//负载
Class<? extends Payload>[] payload() default { };
//指定多个时使用
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Documented
@interface List {
DateCheck[] value();
}
}
4.2 身份证验证
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @version V1.0
* @Author fendo
* @ClassName MobileCheck
* @PackageName
* @Description 身份证验证
* @Data 2017-09-21 10:47
**/
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
//指定验证器
@Constraint(validatedBy = CheckValidator.class)
@Documented
public @interface IdCardCheck {
//默认错误消息
String message() default "身份证格式错误.";
//查询的表名
//分组
Class<?>[] groups() default { };
//负载
Class<? extends Payload>[] payload() default { };
//指定多个时使用
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Documented
@interface List {
IdCardCheck[] value();
}
}
4.3 手机号验证
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @version V1.0
* @Author fendo
* @ClassName MobileCheck
* @PackageName com.gz.medicine.gzyun.health.vaild
* @Description 手机号校验
* @Data 2017-09-21 10:47
**/
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Retention(RUNTIME)
//指定验证器
@Constraint(validatedBy = CheckValidator.class)
@Documented
public @interface MobileCheck {
String message() default "手机号格式错误";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}