在Bean Validation中,除了可以使用现成的校验注解之外,我们还可以在其中自定义自己的代码注解校验规则。
自定义注解——Email
下面是展示的自定义注解,实现的功能是对于电子邮箱的校验。
创建注解接口Email
package com.lyc.valueExtractor;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.PARAMETER}) // 约束注解应用的目标元素类型(METHOD, FIELD, TYPE, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER等)
@Retention(RetentionPolicy.RUNTIME) // 约束注解应用的时机
@Documented
@Constraint(validatedBy ={EmailValidator.class}) // 与约束注解关联的验证器
public @interface Email {
String message() default "这不是有效的电子邮件格式"; // 约束注解验证时的输出消息
Class<?>[] groups() default { }; // 约束注解在验证时所属的组别
Class<? extends Payload>[] payload() default { }; // 约束注解的有效负载
/**
* 邮箱的验证规则
* @return
*/
String regexp() default "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9]+\\.[a-zA-Z]{2,4}";
@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.PARAMETER}) // 约束注解应用的目标元素类型(METHOD, FIELD, TYPE, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER等)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
Email[] value();
}
}
创建注解的实现类EmailValidator
package com.lyc.valueExtractor;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class EmailValidator implements ConstraintValidator<Email,String> {
private String regexp;
@Override
public void initialize(Email constraintAnnotation) {
this.regexp = constraintAnnotation.regexp();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null){
return true;
} else if (value.matches(regexp)){
return true;
}
return false;
}
}
创建应用自定义注解Email的实体类Person2
package com.lyc.validator.entity;
import com.lyc.valueExtractor.Email;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
public class Person2 {
@Email
private String email;
}
创建测试代码Person2Test
package com.lyc.valueExtractor;
import com.lyc.validator.entity.Person2;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Set;
@Slf4j
public class Person2Test {
private static Validator validator;
@BeforeClass
public static void setUpVolidator(){
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
validator = (Validator) validatorFactory.getValidator();
}
@Test
public void manufacturerNull(){
Person2 person2 = new Person2("zhangzhenyihi@@163.com");
Set<ConstraintViolation<Person2>> constraintViolations = validator.validate(person2);
Assert.assertEquals(1,constraintViolations.size());
String errorMessage = constraintViolations.iterator().next().getMessage();
log.info(errorMessage);
Assert.assertEquals("这不是有效的电子邮件格式",errorMessage);
}
}
自定义注解Number
下面是展示的自定义注解,实现的功能是对于输入的数值校验。
创建注解接口Number
package com.lyc.valueExtractor;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.PARAMETER}) // 约束注解应用的目标元素类型(METHOD, FIELD, TYPE, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER等)
@Retention(RetentionPolicy.RUNTIME) // 约束注解应用的时机
@Documented
@Constraint(validatedBy ={NumberValidator.class}) // 与约束注解关联的验证器
public @interface Number {
String message() default "该值应该为数字"; // 约束注解验证时的输出消息
Class<?>[] groups() default { }; // 约束注解在验证时所属的组别
Class<? extends Payload>[] payload() default { }; // 约束注解的有效负载
@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,ElementType.PARAMETER}) // 约束注解应用的目标元素类型(METHOD, FIELD, TYPE, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER等)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
Number[] value();
}
}
创建注解的实现类NumberValidator
package com.lyc.valueExtractor;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class NumberValidator implements ConstraintValidator<Number,Object> {
@Override
public void initialize(Number constraintAnnotation) {
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if(value == null){
return true;
} else {
//数字类型的转换必须得抛异常
if(isNumber(value)){
return true;
}
return false;
}
}
private boolean isNumber(Object value){
NumberHolder numberHolder = new NumberHolder();
return numberHolder.checkNember(value);
}
}
创建数值判断类NumberHolder
package com.lyc.valueExtractor;
public class NumberHolder {
protected boolean checkNember(Object value) {
JudgeNumber judgeNumber = new JudgeNumber();
if(judgeNumber.isNumber(value)){
return true;
} else if(value instanceof String){
String str = (String) value;
if (judgeNumber.isNumber(str)){
return true;
}
}
return false;
}
}
创建数据类型判断泛型类JudgeNumber
package com.lyc.valueExtractor;
public class JudgeNumber<T> {
public boolean isNumber(T value){
if(value instanceof Integer){
Integer integer = (Integer) value;
return true;
} else if(value instanceof Long){
Long longValue= (Long) value;
return true;
} else if(value instanceof Double){
Double doubleValue = (Double) value;
return true;
} else if(value instanceof Float){
Float floatValue = (Float) value;
return true;
}
return false;
}
}
创建应用注解Number的实体类Person
package com.lyc.validator.entity;
import com.lyc.valueExtractor.Number;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
public class Person {
@Number(message= "体重必须为数字") //该注解为自定义注解
private String weight;
@Number(message= "体重必须为数字") //该注解为自定义注解
private Integer weight2;
@Number(message= "体重必须为数字") //该注解为自定义注解
private Double weight3;
@Number(message= "体重必须为数字") //该注解为自定义注解
private Long weight4;
@Number(message= "体重必须为数字") //该注解为自定义注解
private Float weight5;
}
创建Person的测试类PersonTest
package com.lyc.valueExtractor;
import com.lyc.validator.entity.Person;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Set;
@Slf4j
public class PersonTest {
private static Validator validator;
@BeforeClass
public static void setUpVolidator(){
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
validator = (Validator) validatorFactory.getValidator();
}
@Test
public void manufacturerNull(){
Person person = new Person("12s",12,12D,12L,12F);
Set<ConstraintViolation<Person>> constraintViolations = validator.validate(person);
Assert.assertEquals(1,constraintViolations.size());
String errorMessage = constraintViolations.iterator().next().getMessage();
log.info(errorMessage);
Assert.assertEquals("体重必须为数字",errorMessage);
}
}