首页 > 其他分享 >自定义校验器 - List属性值中某个字段的重复性校验

自定义校验器 - List属性值中某个字段的重复性校验

时间:2022-09-19 17:35:57浏览次数:62  
标签:String 自定义 List 校验 private methodNames values import

package com.runachina.sc.designer.domain.validator;

import com.runachina.cloud.starter.base.exception.RestResultException;
import com.runachina.cloud.starter.base.rest.ResultStatus;
import com.runachina.sc.designer.domain.validator.annotations.UniqueField;
import com.runachina.sc.designer.domain.validator.utils.MessageUtil;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class UniqueFieldValidator implements ConstraintValidator<UniqueField, Collection> {

    private String[] fieldNames;

    @Override
    public void initialize(UniqueField constraintAnnotation) {
        this.fieldNames = constraintAnnotation.filedNames();
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    /**
     * getDeclaredField()和 getField() 方法都是获取字段的
     * getField 只能获取 public 的,包括从父类继承来的字段。
     * getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))
     * 因此在获取父类的私有属性时,要通过getSuperclass的之后再通过getDeclaredFiled获取
     */

    @Override
    public boolean isValid(Collection valueList, ConstraintValidatorContext constraintValidatorContext) {
        Map<String, String> valuesMap = new HashMap<>();
        String fields = String.join("&", fieldNames);
        List<String> methodNames = field2method(fieldNames);

        for (Object value : valueList) {
            String values = getValues(value, methodNames);
            if (valuesMap.containsKey(values)) {
                String message = "字段【" + fields + "】的值:" + values + " 重复";
                MessageUtil.setMessage(constraintValidatorContext, message);
                return false;
            }
            valuesMap.put(values, "");
        }
        return true;
    }

    /**
     * 获取属性的值
     */
    private String getValues(Object o, List<String> methodNames) {
        Class<?> aClass = o.getClass();
        List values = new ArrayList();

        // 获取方法的返回值
        for (String methodName : methodNames) {
            try {
                Method method = aClass.getMethod(methodName);
                values.add(method.invoke(o));
            } catch (NoSuchMethodException e) {
                throw new RestResultException(ResultStatus.ILLEGAL_ARGUMENT,
                        "类【" + aClass.getName() + "】中找不到【" + methodName + "】方法");
            } catch (IllegalAccessException e) {
                throw new RestResultException(ResultStatus.ILLEGAL_ARGUMENT,
                        "类【" + aClass.getName() + "】方法【" + methodName + "】拒绝访问");
            } catch (InvocationTargetException e) {
                throw new RestResultException(ResultStatus.ILLEGAL_ARGUMENT,
                        "类【" + aClass.getName() + "】执行方法【" + methodName + "】异常");
            }
        }
        return String.join("&", values);
    }

    /**
     * 字段名转get方法名
     * 因为父类私有属性的值获取不到,得采取调用public的get方法获取属性值
     */
    private List<String> field2method(String[] fieldNames) {
        List<String> methodNames = new ArrayList();
        for (String fieldName : fieldNames) {
            methodNames.add("get" + upperFirst(fieldName));
        }
        return methodNames;
    }

    /**
     * 首字母大写
     */
    private String upperFirst(String name) {
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }

}

 

标签:String,自定义,List,校验,private,methodNames,values,import
From: https://www.cnblogs.com/LcxSummer/p/16708379.html

相关文章