Bean Validation——自定义注解

本文介绍了在Bean Validation中如何自定义注解,包括用于电子邮箱校验的Email注解和数值校验的Number注解。详细讲解了创建注解接口、实现类以及对应的实体类和测试代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  在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);
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值