Springboot custom annotations implement data uniqueness and data existence verification

1. Write a custom annotation CommonFieldValidate that needs to be validated

import com.anglin.common.validate.CommonFieldValidator;
import com.anglin.common.validate.enums.CommonFieldValidateOperatesEnum;
import com.anglin.common.validate.enums.CommonFieldValidateOptionEnum;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Custom Annotation--Field Validation
 *
 * @author zhuzhibin
 * @date 2023/5/16 14:25
 **/
@Target({ElementType. TYPE})
//Must be added when using validator, specified to be used with CommonFieldValidator custom validator
@Constraint(validatedBy = CommonFieldValidator.class)
@Retention(RetentionPolicy. RUNTIME)
public @interface CommonFieldValidate {

    String message() default "The input content verification failed";

    /**
     * Option types are connected with AND or OR
     */
    CommonFieldValidateOptionEnum option() default CommonFieldValidateOptionEnum.AND;

    CommonFieldValidateOperatesEnum [] operates() default {CommonFieldValidateOperatesEnum. UNIQUE};

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

2. Write custom unique annotations and annotations on whether the data exists

import com.baomidou.mybatisplus.extension.activerecord.Model;

import java.lang.annotation.*;

/**
 * Custom annotation verification field uniqueness
 *
 * @author zhuzhibin
 * @date 2023/5/16 14:25
 **/
//Only used for non-null verification of request fields
@Target({ElementType. FIELD})
//Requires jvm runtime to use
@Retention(RetentionPolicy. RUNTIME)
public @interface CommonFieldUniqueValidate {
    /**exist
     * Validated field
     */
    String fieldName() default "";
    /**
     * Error message
     */
    String message() default "Input content verification failed";

    /**
     * Alias Joint query for fields under the same alias
     */
    String alias() default "";

    Class<? extends Model> clazz();

}
package com.anglin.common.annotation;

import com.baomidou.mybatisplus.extension.activerecord.Model;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Custom annotation verification -- field -- whether the data exists
 *
 * @author zhuzhibin
 * @date 2023/5/16 14:25
 **/
//Only used for non-null verification of request fields
@Target({ElementType. FIELD})
//Requires jvm runtime to use
@Retention(RetentionPolicy. RUNTIME)
public @interface CommonFieldYNExistValidate {
    /**exist
     * Validated field
     */
    String fieldName() default "";
    /**
     * Error message
     */
    String message() default "Input content verification failed";

    /**
     * Alias Joint query for fields under the same alias
     */
    String alias() default "";

    Class<? extends Model> clazz();

}

3. Write annotation parser

package com.anglin.common.validate;

import com.anglin.common.annotation.CommonFieldValidate;
import com.anglin.common.util.FieldValidatorUtil;
import com.anglin.common.validate.enums.CommonFieldValidateOperatesEnum;
import com.anglin.common.validate.enums.CommonFieldValidateOptionEnum;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * @Title: FieldUniqueValidator
 * @ProjectName online-plus
 * @Description: field validation
 * @Author ZhuZhiBin
 * @Version
 * @Date 2023/5/16 11:44
 */
public class CommonFieldValidator implements ConstraintValidator<CommonFieldValidate, Object> {

    @Autowired
    FieldValidatorUtil validatorUtil;

    private String message;
    private CommonFieldValidateOperatesEnum[] operates;
    private CommonFieldValidateOptionEnum option;

    @Override
    public void initialize(CommonFieldValidate validator) {
        this. message = validator. message();
        this.operates = validator.operates();
        this.option = validator.option();
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        if(operates != null & amp; & amp; operates. length == 0){
            return true;
        }
        return validatorUtil. validator(message, operates, option, o);
    }
}

4. Write enumeration classes used in annotations

package com.anglin.common.validate.enums;

import com.anglin.common.exception.CommonException;
import lombok. Getter;

/**
 * field validation
 *
 * @date 2023/5/17 14:02
 **/
@Getter
public enum CommonFieldValidateOperatesEnum {

    /** Uniqueness */
    UNIQUE("UNIQUE"),

    /** does it exist */
    YN_EXIST("YN_EXIST");

    private final String value;


    CommonFieldValidateOperatesEnum(String value) {
        this.value = value;
    }

    public static void validate(String value) {
        boolean flag = UNIQUE.getValue().equals(value) || YN_EXIST.getValue().equals(value);
        if(!flag) {
            throw new CommonException("This verification method is not supported: {}", value);
        }
    }
}
package com.anglin.common.validate.enums;

import com.anglin.common.exception.CommonException;
import lombok. Getter;

/**
 * Validate whether the field option is and or or
 *
 * @date 2023/5/17 14:02
 **/
@Getter
public enum CommonFieldValidateOptionEnum {

    /** Association **/
    AND("AND"),

    /** non-associated **/
    OR("OR");

    private final String value;


    CommonFieldValidateOptionEnum(String value) {
        this.value = value;
    }

    public static void validate(String value) {
        boolean flag = AND.getValue().equals(value) || OR.getValue().equals(value);
        if(!flag) {
            throw new CommonException("This verification method is not supported: {}", value);
        }
    }
}

5. Write the verification Util

package com.anglin.common.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.anglin.common.annotation.CommonFieldUniqueValidate;
import com.anglin.common.annotation.CommonFieldYNExistValidate;
import com.anglin.common.validate.enums.CommonFieldValidateOperatesEnum;
import com.anglin.common.validate.enums.CommonFieldValidateOptionEnum;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.validation.ValidationException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Title: FieldUniqueUtils
 * @ProjectName online-plus
 * @Description: Field uniqueness verification tool class
 * @Author ZhuZhiBin
 * @Version
 * @Date 2023/5/16 11:48
 */
@Slf4j
@Component
public class FieldValidatorUtil {

    /**
     * The id field in the entity class
     */
    private String idColumnName;

    /**
     * The value of id in the entity class
     */
    private Object idColumnValue;

    private final String declaredField = "memberValues";
    private final String annotateAttribute = "fieldName";
    private final String objKey = "obj";
    private final String msgKey = "msg";

    /**
     * First, obtain the list under different options of custom annotations on vo or dto by traversing
     * Annotation on the null value field does not proceed to the next step of judgment
     * @param message
     * @param operates
     * @param option
     * @param o
     * @return
     */
    public boolean validator(String message, CommonFieldValidateOperatesEnum[] operates, CommonFieldValidateOptionEnum option, Object o) {
        Field[] fields = ReflectUtil. getFields(o. getClass());
        List<CommonFieldUniqueValidate> commonFieldUniqueValidateList = new LinkedList<>();
        List<CommonFieldYNExistValidate> commonFieldYNExistValidateList = new LinkedList<>();

        Map<String,Object> queryUniqueValidateMap = new HashMap<>();
        Map<String,Object> queryYNExistValidateMap = new HashMap<>();

        boolean unique = ArrayUtil.contains(operates, CommonFieldValidateOperatesEnum.UNIQUE);
        boolean ynExist = ArrayUtil.contains(operates, CommonFieldValidateOperatesEnum.YN_EXIST);

        for (Field f : fields) {
            Object fieldValue = ReflectUtil. getFieldValue(o, f);
            // exclude empty fields
            if (ObjectUtil. isNull(fieldValue)) {
                continue;
            }
            // unique verification
            if(unique){
                uniqueBuilder(f, fieldValue, commonFieldUniqueValidateList, queryUniqueValidateMap);
            }
            //Is there a verification
            if(ynExist){
                ynExistBuilder(f, fieldValue, commonFieldYNExistValidateList, queryYNExistValidateMap);
            }
        }
        boolean res = true;
        if(ArrayUtil.contains(operates, CommonFieldValidateOperatesEnum.UNIQUE) & amp; & amp; CollectionUtil.isNotEmpty(commonFieldUniqueValidateList)){
            res = uniqueValidator(CommonFieldValidateOperatesEnum.UNIQUE, message, option, commonFieldUniqueValidateList, queryUniqueValidateMap, o);
        }
        if(ArrayUtil.contains(operates, CommonFieldValidateOperatesEnum.YN_EXIST) & amp; & amp; CollectionUtil.isNotEmpty(commonFieldYNExistValidateList)){
            res = yNExistValidator(CommonFieldValidateOperatesEnum.YN_EXIST, message, option,commonFieldYNExistValidateList, queryYNExistValidateMap, o);
        }
        return res;
    }

    /**
     * does it exist
     * Assemble our attributes and values in the map to facilitate subsequent splicing conditions
     * @param f
     * @param fieldValue
     * @param commonFieldYNExistValidateList
     * @param queryYNExistValidateMap
     */
    private void ynExistBuilder(Field f, Object fieldValue, List<CommonFieldYNExistValidate> commonFieldYNExistValidateList, Map<String, Object> queryYNExistValidateMap) {
        CommonFieldYNExistValidate commonFieldYNExistValidate = f.getAnnotation(CommonFieldYNExistValidate.class);
        if(commonFieldYNExistValidate != null){
            String fieldName = StrUtil.isEmpty(commonFieldYNExistValidate.fieldName()) ? StrUtil.toUnderlineCase(f.getName())
                    : commonFieldYNExistValidate.fieldName();
            dynamicAnnotateAttribute(commonFieldYNExistValidate, fieldName);
            commonFieldYNExistValidateList.add(commonFieldYNExistValidate);
            queryYNExistValidateMap.put(fieldName, fieldValue);
        }
    }


    /**
     * uniqueness
     * Assemble our attributes and values in the map to facilitate subsequent splicing conditions
     * Dynamically assign values to annotation attributes Code processing is mainly for fear of irregularities in the later use of annotations
     * @param f
     * @param fieldValue
     * @param commonFieldUniqueValidateList
     * @param queryUniqueValidateMap
     */
    private void uniqueBuilder(Field f, Object fieldValue, List<CommonFieldUniqueValidate> commonFieldUniqueValidateList, Map<String, Object> queryUniqueValidateMap) {
        CommonFieldUniqueValidate commonFieldUniqueValidate = f.getAnnotation(CommonFieldUniqueValidate.class);
        if(commonFieldUniqueValidate != null){
            String fieldName = StrUtil.isEmpty(commonFieldUniqueValidate.fieldName()) ? StrUtil.toUnderlineCase(f.getName())
                    : commonFieldUniqueValidate.fieldName();
            dynamicAnnotateAttribute(commonFieldUniqueValidate, fieldName);
            commonFieldUniqueValidateList.add(commonFieldUniqueValidate);
            queryUniqueValidateMap.put(fieldName, fieldValue);
        }
    }

    /**
     * Dynamically adjust the fieldName attribute value of the custom annotation
     *
     * @param annotate annotation
     * @param fieldName
     */
    private void dynamicAnnotateAttribute(Object annotate, String fieldName) {
        //Get the InvocationHandler held by the proxy instance of foo
        InvocationHandler h = Proxy. getInvocationHandler(annotate);
        // Get the memberValues field of AnnotationInvocationHandler
        Field hField = null;
        try {
            hField = h. getClass(). getDeclaredField(declaredField);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        //Because this field is private final decoration, so you need to open the permission
        hField. setAccessible(true);
        // get memberValues
        Map memberValues = null;
        try {
            memberValues = (Map) hField. get(h);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        // Modify the value attribute value
        memberValues. put(annotateAttribute, fieldName);
    }


    /**
     * Field information unique verification
     * Perform logical processing according to the attribute information on the custom annotation
     * Acquire objects according to class Perform subsequent persistence and other operations according to mybatis-plus active-record operations
     *
     *
     * @param unique
     * @param option
     * @param commonFieldUniqueValidates
     * @param queryUniqueValidateMap
     * @param o
     * @return
     */
    public boolean uniqueValidator(CommonFieldValidateOperatesEnum unique, String message, CommonFieldValidateOptionEnum option, List<CommonFieldUniqueValidate> commonFieldUniqueValidates, Map<String, Object> queryUniqueValidateMap, Object o){
        //alias to group
        Map<String, List<CommonFieldUniqueValidate>> collect =
                commonFieldUniqueValidates.stream().collect(Collectors.groupingBy(CommonFieldUniqueValidate::alias));
        boolean res = true;
        for (String key : collect. keySet()) {

            if(CommonFieldValidateOptionEnum.AND.equals(option)) {
                Map<String, Object> stringObjectMap = uniqueValidatorBuilder(collect.get(key).get(0), message, o);
                checkUpdateOrSave(stringObjectMap. get(objKey));
                Object msg = stringObjectMap. get(msgKey);
                res = checkBuilder(unique, queryUniqueValidateMap, stringObjectMap.get(objKey), msg.toString());
            } else {
                List<CommonFieldUniqueValidate> commonFieldUniqueValidateList = collect.get(key);
                for (CommonFieldUniqueValidate commonFieldUniqueValidate : commonFieldUniqueValidateList) {
                    Map<String,Object> queryMap = new HashMap<>();
                    Map<String, Object> stringObjectMap = uniqueValidatorBuilder(commonFieldUniqueValidate, message, o);
                    checkUpdateOrSave(stringObjectMap. get(objKey));
                    Object msg = stringObjectMap. get(msgKey);
                    queryMap.put(commonFieldUniqueValidate.fieldName(), queryUniqueValidateMap.get(commonFieldUniqueValidate.fieldName()));
                    res = checkBuilder(unique, queryMap, stringObjectMap.get(objKey), msg.toString());
                    if(!res){
                        return res;
                    }
                }
            }
        }
        return res;
    }

    private Map<String,Object> uniqueValidatorBuilder(CommonFieldUniqueValidate commonFieldUniqueValidate, String message, Object o) {
        Map<String,Object> map = new HashMap();
        Object obj = null;
        if(ObjectUtil.isNotNull(commonFieldUniqueValidate.clazz())){
            try {
                obj = commonFieldUniqueValidate.clazz().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        String msg = commonFieldUniqueValidate. message();
        if (null == obj) {
            obj = o;
        } else {
            BeanUtils. copyProperties(o, obj);
        }
        msg = StrUtil.isEmpty(msg) ? message : msg;
        map.put(objKey, obj);
        map.put(msgKey, msg);
        return map;
    }

    /**
     * Field information unique verification
     * Perform logical processing according to the attribute information on the custom annotation
     * Acquire objects according to class Perform subsequent persistence and other operations according to mybatis-plus active-record operations
     *
     *
     * @param ynExist
     * @param option
     * @param commonFieldYNExistValidates
     * @param queryYNExistValidateMap
     * @param o
     * @return
     */
    public boolean yNExistValidator(CommonFieldValidateOperatesEnum ynExist, String message, CommonFieldValidateOptionEnum option, List<CommonFieldYNExistValidate> commonFieldYNExistValidates, Map<String, Object> queryYNExistValidateMap, Object o){
        //alias to group
        Map<String, List<CommonFieldYNExistValidate>> collect =
                commonFieldYNExistValidates.stream().collect(Collectors.groupingBy(CommonFieldYNExistValidate::alias));
        boolean res = true;
        for (String key : collect. keySet()) {
            if(CommonFieldValidateOptionEnum.AND.equals(option)) {
                Map<String, Object> stringObjectMap = yNExistValidatorBuilder(collect.get(key).get(0), message, o);
                checkUpdateOrSave(stringObjectMap. get(objKey));
                Object msg = stringObjectMap. get(msgKey);
                res = checkBuilder(ynExist, queryYNExistValidateMap, stringObjectMap.get(objKey), msg.toString());
            } else {
                for (CommonFieldYNExistValidate commonFieldYNExistValidate : collect.get(key)) {
                    Map<String,Object> queryMap = new HashMap<>();
                    Map<String, Object> stringObjectMap = yNExistValidatorBuilder(commonFieldYNExistValidate, message, o);
                    checkUpdateOrSave(stringObjectMap. get(objKey));
                    Object msg = stringObjectMap. get(msgKey);
                    queryMap.put(commonFieldYNExistValidate.fieldName(), queryYNExistValidateMap.get(commonFieldYNExistValidate.fieldName()));
                    res = checkBuilder(ynExist, queryMap, stringObjectMap.get(objKey), msg.toString());
                    if(!res){
                        return res;
                    }
                }
            }
        }
        return res;
    }

    private Map<String, Object> yNExistValidatorBuilder(CommonFieldYNExistValidate commonFieldYNExistValidate, String message, Object o) {

        Map<String,Object> map = new HashMap();
        Object obj = null;
        if(ObjectUtil.isNotNull(commonFieldYNExistValidate.clazz())){
            try {
                obj = commonFieldYNExistValidate.clazz().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        String msg = commonFieldYNExistValidate. message();
        if (null == obj) {
            obj = o;
        } else {
            BeanUtils. copyProperties(o, obj);
        }
        msg = StrUtil.isEmpty(msg) ? message : msg;
        map.put(objKey, obj);
        map.put(msgKey, msg);
        return map;
    }


    /**
     * Determine whether to update or save by whether the value of the @TableId annotation in the incoming entity class is empty
     * Assign the value id value and id column name
     * The value of id is not empty, it is an update, otherwise it is an insert
     * @param o Annotated entity class
     * @return
     */
    public void checkUpdateOrSave(Object o){
        Field[] fields = getAllFields(o. getClass());
        for (Field f: fields) {
            // Set private properties to be readable
            f. setAccessible(true);
            if(f.isAnnotationPresent(TableId.class)){
                TableId tableId = f. getAnnotation(TableId. class);
                idColumnName = tableId. value();
                try {
                    idColumnValue = f. get(o);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * Method to get the attributes of this class and its parent class
     * @param clazz current class object
     * @return field array
     */
    private static Field[] getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz. getSuperclass();
        }
        Field[] fields = new Field[fieldList. size()];
        return fieldList.toArray(fields);
    }


    /**
     * Obtain whether the data is repeated through the incoming field value
     * @param operate
     * @param queryMap
     * @param o
     * @param message
     * @return
     */
    public boolean checkBuilder(CommonFieldValidateOperatesEnum operate, Map<String, Object> queryMap, Object o, String message){
        Model model = (Model) o;
        QueryWrapper queryWrapper = new QueryWrapper();
        for(String key : queryMap. keySet()){
            queryWrapper.eq(key, queryMap.get(key));
        }
        if(operate.equals(CommonFieldValidateOperatesEnum.UNIQUE)){
            if(idColumnValue != null){
                //Update, the condition must exclude itself
                queryWrapper.ne(idColumnName, idColumnValue);
            }
            if (model. selectCount(queryWrapper) > 0){
                log. error(message);
                throw new ValidationException(message);
            }
        } else if(operate.equals(CommonFieldValidateOperatesEnum.YN_EXIST) & amp; & amp; model.selectCount(queryWrapper) < 0){
            log. error(message);
            throw new ValidationException(message);
        }
        return true;
    }


}

6. Write the verified dto

package com.anglin.biz.modular.user.param;

import com.anglin.biz.modular.user.entity.BizUser;
import com.anglin.common.annotation.CommonFieldUniqueValidate;
import com.anglin.common.annotation.CommonFieldValidate;
import com.anglin.common.annotation.CommonPhoneOrEmail;
import com.anglin.common.validate.enums.CommonFieldValidateOperatesEnum;
import com.anglin.common.validate.enums.CommonFieldValidateOptionEnum;
import com.anglin.common.validate.enums.CommonPhoneOrEmailTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok. Getter;
import lombok. Setter;

import javax.validation.constraints.NotBlank;

/**
 * Personnel addition parameters
 *
 * @date 2022/7/26 15:36
 **/
@Getter
@Setter
@CommonFieldValidate(operates = {CommonFieldValidateOperatesEnum.UNIQUE}, option = CommonFieldValidateOptionEnum.OR, message = "User data validation failed, please re-enter")
public class BizUserAddParam {

    /** account */
    @ApiModelProperty(value = "Account", required = true, position = 1)
    @NotBlank(message = "account cannot be empty")
    @CommonFieldUniqueValidate(fieldName = "account", message = "Duplicate account exists, please re-enter", clazz = BizUser.class, alias = "bizUser")
    private String account;

    /** Name */
    @ApiModelProperty(value = "Name", required = true, position = 2)
    @NotBlank(message = "name cannot be empty")
    private String name;

    /** organization id */
    @ApiModelProperty(value = "Organization id", required = true, position = 3)
    @NotBlank(message = "orgId cannot be empty")
    private String orgId;

    /** post id */
    @ApiModelProperty(value = "post id", required = true, position = 4)
    @NotBlank(message = "positionId cannot be empty")
    private String positionId;

    /** post level */
    @ApiModelProperty(value = "post level", position = 5)
    private String positionLevel;

    /** supervisor id */
    @ApiModelProperty(value = "Supervisor id", position = 6)
    private String directorId;

    /** avatar */
    @ApiModelProperty(value = "Avatar, picture base64", position = 7)
    private String avatar;

    /** sign */
    @ApiModelProperty(value = "signature, image base64", position = 8)
    private String signature;

    /** Nick name */
    @ApiModelProperty(value = "nickname", position = 9)
    private String nickname;

    /** gender */
    @ApiModelProperty(value = "gender", position = 10)
    private String gender;

    /** age */
    @ApiModelProperty(value = "age", position = 11)
    private String age;

    /** date of birth */
    @ApiModelProperty(value = "Date of Birth", position = 12)
    private String birthday;

    /** nationality */
    @ApiModelProperty(value = "ethnicity", position = 13)
    private String nation;

    /** Native place */
    @ApiModelProperty(value = "Hometown", position = 14)
    private String nativePlace;

    /** Home address */
    @ApiModelProperty(value = "home address", position = 15)
    private String homeAddress;

    /** contact address */
    @ApiModelProperty(value = "communication address", position = 16)
    private String mailingAddress;

    /** type of certificate */
    @ApiModelProperty(value = "Certificate Type", position = 17)
    private String idCardType;

    /** ID number */
    @ApiModelProperty(value = "ID number", position = 18)
    private String idCardNumber;

    /** Culture level */
    @ApiModelProperty(value = "education level", position = 19)
    private String cultureLevel;

    /** political status */
    @ApiModelProperty(value = "Political Aspect", position = 20)
    private String politicalOutlook;

    /** graduated school */
    @ApiModelProperty(value = "graduate school", position = 21)
    private String college;

    /** Educational background */
    @ApiModelProperty(value = "education", position = 22)
    private String education;

    /** School system */
    @ApiModelProperty(value = "School System", position = 23)
    private String eduLength;

    /** Bachelor of Science */
    @ApiModelProperty(value = "degree", position = 24)
    private String degree;

    /** cell phone */
    @ApiModelProperty(value = "Mobile phone", position = 25)
    @CommonPhoneOrEmail(message = "The phone number format is incorrect", type = CommonPhoneOrEmailTypeEnum.PHONE)
    @CommonFieldUniqueValidate(fieldName = "phone", message = "There is a duplicate phone number, please re-enter", clazz = BizUser.class, alias = "bizUser")
    private String phone;

    /** Mail */
    @ApiModelProperty(value = "Mailbox", position = 26)
    @CommonPhoneOrEmail(message = "The email format is incorrect", type = CommonPhoneOrEmailTypeEnum.EMAIL)
    @CommonFieldUniqueValidate(fieldName = "email", message = "Duplicate email exists, please re-enter", clazz = BizUser.class, alias = "bizUser")
    private String email;

    /** home phone */
    @ApiModelProperty(value = "Home Phone", position = 27)
    private String homeTel;

    /** Office Phone */
    @ApiModelProperty(value = "office phone", position = 28)
    private String officeTel;

    /** emergency contact */
    @ApiModelProperty(value = "Emergency Contact", position = 29)
    private String emergencyContact;

    /** Emergency contact number */
    @ApiModelProperty(value = "Emergency contact number", position = 30)
    private String emergencyPhone;

    /** Emergency contact address */
    @ApiModelProperty(value = "emergency contact address", position = 31)
    private String emergencyAddress;

    /** employee ID */
    @ApiModelProperty(value = "employee number", position = 32)
    private String empNo;

    /** Entry date */
    @ApiModelProperty(value = "employee number", position = 33)
    private String entryDate;

    /** concurrent information */
    @ApiModelProperty(value = "concurrent information", position = 34)
    private String positionJson;

    /** Sort code */
    @ApiModelProperty(value = "sort code", position = 35)
    private Integer sortCode;

    /** Extended Information */
    @ApiModelProperty(value = "extended information", position = 36)
    private String extJson;
}

Seven, write the controller

/**
     * Add people
     *
     * @date 2022/4/24 20:47
     */
    @ApiOperationSupport(order = 2)
    @ApiOperation("Add Person")
    @CommonLog("Add Person")
    @SaCheckPermission("/biz/user/add")
    @PostMapping("/biz/user/add")
    public CommonResult<String> add(@RequestBody @Valid BizUserAddParam bizUserAddParam) {
        bizUserService.add(bizUserAddParam);
        return CommonResult.ok();
    }