参考:http://developer.51cto.com/art/201104/253257_all.htm
自定义注解主要适用于数据格式值域校验,像javax.validation.constraints 中的@Blank,@Max,@DecimalMax等有时候可能不会满足我们的需求。
一.简单的注解
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {MaxValue.Validator.class})
public @interface MaxValue {
String max() default "";
String message() default " ";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public static @interface List {
public abstract MaxValue[] value();
}
class Validator implements ConstraintValidator<MaxValue, String> {
private String maxValue;
@Override
public void initialize(MaxValue paramA) {
this.maxValue = paramA.max();
}
@Override
public boolean isValid(String paramT,ConstraintValidatorContext context) {
//写验证,不通过时 return false;
if (!StringUtils.isEmpty(paramT))
{
if(!StringUtils.isEmpty(maxValue)){
if(Double.valueOf(paramT)>Double.valueOf(maxValue)){
return false;
}
}
}
return true;
}
}
}
其中被校验的String 也可以是对象,这样可以验证一个对象中多个值间的关系
二.注意
1.级联验证
使用 @Valid 注解 比如内部类中的参数
2.多值约束
只需要在定义约束注解的同时定义一个 List(@interface List{})。使用该约束注解时,Bean Validation 将 value 数组里面的每一个元素都处理为一个普通的约束注解,并对其进行验证,所有约束条件均符合时才会验证通过。
@Target({ METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@interface List {
NotEmpty2[] value();
}
使用
@Setter
@Getter
@ToString
public class TestDto {
@MaxValue(max="60",message="XXX最大值是60")
private String result;
private String check_time;
// 不加 @Valid 不会校验
@Valid
private LifeDto life;
@Valid
private List<BloodDto> blood;
}
校验 返回拼接的msg
private <T> String validMessage(T dto){
if(null == dto || allItemIsNull(dto)){
return "";
}
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
Set<ConstraintViolation<T>> constraint = validator.validate(dto);
StringBuffer returnMessage = new StringBuffer("");
if(CollectionUtils.isNotEmpty(constraint)){
StringBuffer validMessage = new StringBuffer("");
constraint.forEach(o->validMessage.append(o.getMessage()+","));
returnMessage.append(validMessage);
}
return returnMessage.toString();
}
// 如果一个类的成员变量所有字段都为空就不校验了
private boolean allItemIsNull(Object obj) {
Class<?> clazz=obj.getClass(); //得到类对象
Field[] fs=clazz.getDeclaredFields(); //得到属性集合
try{
for(Field field:fs){ //遍历属性
field.setAccessible(true); //设置属性是可以访问的(私有的也可以)
if(field.get(obj)!=null && field.get(obj)!="" && field.getName()!= "serialVersionUID"){
return false;
}
}
}catch(Exception e){
throw new BusinessException("判断成员变量是否为空时出错!"+e.getMessage(),e);
}
return true;
}