使用反射对属性进行校验

背景:请求参数个数多,类型多,校验的场景多

1.自定义属性校验注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ConditionalValidation {
    String[] value();
}

2.创建请求实体,该例子中包含了类中属性是集合的场景

class MyObject {
    @ConditionalValidation({"scenario1", "scenario3"})
    private String property1;

    @ConditionalValidation({"scenario1"})
    private Integer property2;

    @ConditionalValidation({"scenario1", "scenario2"})
    private BigDecimal property3;

    @ConditionalValidation({"scenario1", "scenario3"})
    private List<MySubObject> property4;

    // ... other properties

    // Getters and setters

    class MySubObject {
        @ConditionalValidation({"scenario1", "scenario3"})
        private String subProperty;

        // ... other properties

        // Getters and setters
    }
}

3.编写校验方法,该例子中包含了几种类型:String、Integer、List

public static List<String> validateProperties(Object object, String[] validationScenarios) {
        List<String> validationErrors = new ArrayList<>();
        
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        
        Field[] fields = object.getClass().getDeclaredFields();
        for (Field field : fields) {
            ConditionalValidation conditionalValidation = field.getAnnotation(ConditionalValidation.class);
            if (conditionalValidation != null && Arrays.stream(conditionalValidation.value())
                    .anyMatch(value -> Arrays.asList(validationScenarios).contains(value))) {
                try {
                    field.setAccessible(true);
                    Object fieldValue = field.get(object);
                    
                    if (fieldValue == null) {
                        validationErrors.add("Property '" + field.getName() + "' cannot be null");
                    } else if (fieldValue instanceof String && ((String) fieldValue).isEmpty()) {
                        validationErrors.add("Property '" + field.getName() + "' cannot be empty");
                    } else if (fieldValue instanceof Integer && (Integer) fieldValue == 0) {
                        validationErrors.add("Property '" + field.getName() + "' cannot be zero");
                    } else if (fieldValue instanceof BigDecimal && ((BigDecimal) fieldValue).compareTo(BigDecimal.ZERO) == 0) {
                        validationErrors.add("Property '" + field.getName() + "' cannot be zero");
                    } else if (fieldValue instanceof List) {
                        List<?> listValue = (List<?>) fieldValue;
                        for (Object listItem : listValue) {
                            validationErrors.addAll(validateProperties(listItem, validationScenarios));
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return validationErrors;
    }

4.编写测试例子,调用该校验方法

public static void main(String[] args) {
        MyObject myObject = new MyObject();
        myObject.setProperty1("value");
        myObject.setProperty2(0); // Invalid value for testing
        myObject.setProperty3(new BigDecimal("10.5"));
        myObject.setProperty4(new ArrayList<>()); // Empty List for testing

        List<String> validationErrors = validateProperties(myObject, new String[]{"scenario1", "scenario3"});

        if (validationErrors.isEmpty()) {
            System.out.println("No validation errors.");
        } else {
            System.out.println("Validation errors:");
            for (String error : validationErrors) {
                System.out.println("- " + error);
            }
        }
    }

在上边这个例子中,我们通过传入的场景参数,来控制校验的属性。特别适合在拥有大批量属性的实体类进行校验的场景使用,避免过多的if判断,如果要调整校验逻辑,简单可控。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值