自定义注解实现字段有条件的判空

标签: java 自定义注解 判空

背景
自定义注解实现字段有条件的判空,例如Student有三个字段name、age、sex;name、age不能为空,sex只有当age=18时不能为空(可能例子不是很符合实际场景,只为实现说明)

代码实现
1、新建自动以注解类

基本元注解含义请自行学习@Target、@Retention、@Documented、@Inherited。本例@ConditionalNotEmpty注解有三个参数message、conditionFiledName、contionString,含义分别为错误提示信息、判断依据的字段名称、判断条件(如本例中如果age=18,则sex不能为空)。可以自行设置参数默认值,如果参数没有默认值则在使用注解时必须要明确传递参数值
package com.atguigu.springcloud.annotation;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConditionalNotEmpty {
 
    //错误提示信息
    String message();
 
    //判断依据的字段名称
    String conditionFiledName() default "";
 
    //判断条件,如本例中 18
    String contionString() default "";
}
2、新建Student类

建议使用lombok注解减少代码量,可以看到注解的参数message必须赋值,否则会报错,conditionFiledName、contionString在自定义注解中已经执行默认值为"",所有不明确赋值也不会报错。在sex字段使用注解的含义为如果age=18则sex不能为空
package com.atguigu.springcloud.annotation;
 
import lombok.Data;
 
@Data
public class Student {
    @ConditionalNotEmpty(message = "name不能为空")
    private String name;
    @ConditionalNotEmpty(message = "age不能为空")
    private String age;
    @ConditionalNotEmpty(message = "sex不能为空",conditionFiledName = "age",contionString = "18")
    private String sex;
 
    public Student(String name, String age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}
3、新建ConditionalNotEmptyExplain类

利用反射解析注解,详细注释如下代码。实际开发中可以直接调用也可以使用AOP去判空
package com.atguigu.springcloud.annotation;
 
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Field;
 
public class ConditionalNotEmptyExplain {
    public static void validate(T t) throws IllegalAccessException, NoSuchFieldException {
        // 获取当前对象所有字段信息
        Field[] declaredFields = t.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            // 判断字段是否被注解 ConditionalNotEmpty 解释
            if (field.isAnnotationPresent(ConditionalNotEmpty.class)) {
                // 功能是启用或禁用安全检查,设置为true
                field.setAccessible(true);
                // field.get(t)获取当前字段值,如果有值则判断下个字段
                if (field.get(t) != null) {
                    continue;
                }
                // field.get(t)获取当前字段值,如果为空则继续判断是否需要条件判断
                ConditionalNotEmpty annotation = field.getAnnotation(ConditionalNotEmpty.class);
                // 获取message参数值
                String message = annotation.message();
                // 获取conditionFiledName参数值
                String conditionFiledName = annotation.conditionFiledName();
                // 获取contionString参数值
                String contionString = annotation.contionString();
                // 如果conditionFiledName和contionString不为空,则直接打印出message
                if (StringUtils.isNotEmpty(conditionFiledName) && StringUtils.isNotEmpty(contionString)) {
                    // 根据依赖字段conditionFiledName(比如本例字段age),反射得到这个依赖字段的信息
                    Field conditionFiled = t.getClass().getDeclaredField(conditionFiledName);
                    conditionFiled.setAccessible(true);
                    // 获取当前依赖字段值(比如本例字段age)
                    Object conditionFiledValue = conditionFiled.get(t);
                    // 进行判断如果当前依赖字段值等于注解参数contionString值则满足条件(本例当前字段age值10等于注解参数contionString10,则打印)
                    if (conditionFiledValue != null && contionString.equals(conditionFiledValue)) {
                        if (field.get(t) == null) {
                            System.out.println("当"+conditionFiled.getName()+"为"+conditionFiledValue+"时"+message);
                            continue;
                        }
                    }
                }else {
                    // 如果conditionFiledName和contionString为空,则直接打印出message
                    System.out.println(message);
                }
            }
        }
    }
}
4、测试结果

// 1、当name、age、sex都为空时
public class TestMain {
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
        Student student = new Student(null,null,null);
        ConditionalNotEmptyExplain.validate(student);
    }
}
控制台打印结果:
name不能为空
age不能为空
 
 
// 2、当age、sex为空时
public class TestMain {
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
        Student student = new Student("zhangsan",null,null);
        ConditionalNotEmptyExplain.validate(student);
    }
}
控制台打印结果:
age不能为空
 
 
// 3、当age=18、sex为空时
public class TestMain {
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
        Student student = new Student("zhangsan","18",null);
        ConditionalNotEmptyExplain.validate(student);
    }
}
控制台打印结果:
当age为18时sex不能为空
 
 
// 4、当age=19、sex为空时
public class TestMain {
    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
        Student student = new Student("zhangsan","18",null);
        ConditionalNotEmptyExplain.validate(student);
    }
}
 
控制台打印结果:
没有打印结果

你可能感兴趣的:(springboot,java,java)