首页 > 其他分享 >实现注解校验Dto字段是否为空

实现注解校验Dto字段是否为空

时间:2024-10-30 10:31:22浏览次数:7  
标签:dto NotNullField 校验 field 字段 为空 Dto 注解 public

一、背景

我们用json对象作为接收参数的包装器,最后要转化为dto进行业务操作,操作之前要做非空校验,我们可以实现2个注解来实现这个通用的操作。@NotNullField @CheckNull

二、思路

1.实现@NotNullField注解,注解标记在dto字段名上面

@Target(ElementType.FIELD) // 目标为字段
@Retention(RetentionPolicy.RUNTIME) // 运行时可用
public @interface NotNullField {
    String fieldName() default ""; // 可自定义字段名
    String message() default "字段不能为空"; // 默认错误消息
}

image
2.实现@CheckNull注解,注解标记在调用方法上面,这个是要接受dto.class的
image

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckNull {
    //要校验的dto
    Class<?> value();
}

三、代码实现

1.@NotNullField,这个我实现了一个静态方法

 /**
     * 校验标注了非空字段的dto
     * @param obj
     * @throws NullParamsException
     */
    public static void validateNotNull(Object obj) throws NullParamsException {

        Class<?> clazz = obj.getClass();

        while (clazz != null) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(NotNullField.class)) {
                    field.setAccessible(true); // 允许访问私有字段
                    try {
                        Object value = field.get(obj);
                        if (value == null) {
                            NotNullField annotation = field.getAnnotation(NotNullField.class);
                            throw new NullParamsException(
                                    String.format("验证错误: %s - %s", annotation.fieldName(), annotation.message())
                            );
                        }else{
                            //如果是集合类型递归调用
                            //感觉递归调用 是一个危险的方式 大数据量会导致栈内存溢出 先进行实验
                            //代码中如果有集合的方式必须 业务自己提取出来data自己去遍历校验
                            if(Collections.class.isAssignableFrom(field.getType())){
                                field.setAccessible(true); // 允许访问私有字段
                                Collection<?> collection = (Collection<?>) value;
                                Iterator<?> iterator = collection.iterator();
                                while (iterator.hasNext()) {
                                    Object item = iterator.next();
                                    // 处理集合中的每个对象
                                    validateNotNull(item);
                                }
                            }
                        }
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException("访问错误", e);
                    }
                }
            }
            // 移动到父类 要支持继承
            clazz = clazz.getSuperclass();
        }
    }

2.@CheckNull,这里的@Order 注解是标记注解起作用的顺序,因为我还写了其他校验注解

@Component
@Aspect
@Order(2)
public class CheckNullAspect {
    @Autowired
    private MyAutoConfig myAutoConfig;
    /**
     * 环绕处理
     * 连接点
     * 注解的全限定名称
     * @return 结果
     * @throws Throwable 异常
     */
    @Pointcut(value = "@annotation(具体包)")
    public void checkAround() throws Throwable {

    }

    @Before("checkAround()")
    public void around(JoinPoint proceedingJoinPoint) throws Throwable {
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        //获取操作
        CheckNull annotation = method.getAnnotation(CheckNull.class);
        Class<?> dtoClass = annotation.value();
        // 获取入参
        Object[] objects = proceedingJoinPoint.getArgs();

        if (Objects.nonNull(objects) && objects.length > 0) {
            JSONObject jsonObject = (JSONObject) objects[0];
            Object dto = jsonObject.toJavaObject(dtoClass);
            CheckUtil.validateNotNull(dto);
        }
    }
}

四、后记

自定义注解实现在spring类型的项目里面超好用!

标签:dto,NotNullField,校验,field,字段,为空,Dto,注解,public
From: https://www.cnblogs.com/lovefoolself/p/18515318

相关文章

  • PyImport_ImportModule总是返回 NULL或者空调用失败pModule为空pFunc为空
    问题1pModule为空c++调用Python时,要调用Python自定义函数,但是在调用PyImport_ImportModule时,总是返回空。一直调用不成功,明明我已经通过pyList_append(syspath,目录路径)。但是就是找不到。正常用cmd脚本也能正常运行。解决方案//初始化Python解释器Py_Initialize();//......
  • 用正则表达式获取json字段排序
    varReg01=newRegex($"\"fd9e\"\\s*?:\\s*?(\".*?)\"");varReg02=newRegex($"\"fe1e\"\\s*?:\\s*?(\".*?)\"");dtoList=dtoList.Select(a=>new{ dto=a,H=getMatchReg01(Reg02......
  • SqlSugar 达梦数据库大数据量,长字符串添加,数据库为空
    SqlSugar实体添加数据时,发现字符串超过某个长度,在数据库中就空白,插入失败,原因如下:达梦Clob、Text类型用法版本需升级到5.1.4.92及以上版本//需在长字符串的属性中加入以下[SugarColumn(SqlParameterDbType=typeof(NClobPropertyConvert))]publicstringName{get;......
  • 三周精通FastAPI:8 请求体 - 多个参数、字段、嵌套模型
    本节内容对应FastAPI手册的三节,分别是请求体-多个参数,请求体-字段和请求体-嵌套模型。手册: https://fastapi.tiangolo.com/zh/tutorial/body-multiple-params/源代码示例是python3.10及以上版本。请求体-多个参数¶既然我们已经知道了如何使用 Path 和 Query,下面让......
  • day02|计算机网络重难点之HTTP请求报文和响应报文、HTTP的请求方式(方法字段)、GET请求
    day02|计算机网络重难点之HTTP请求报文和响应报文、HTTP的请求方式(方法字段)、GET请求和POST请求的区别3.HTTP请求报文和响应报文是怎样的,有哪些常见的字段?4.HTTP有哪些请求方式?(即方法字段的不同取值)5.GET请求和POST请求的区别3.HTTP请求报文和响应报文是怎样的,有哪......
  • IDEA 不提示 gitlab-ci 字段问题
    问题描述idea编写.gitlab-ci.yml文件没有代码提示正常来说,idea会识别到类型自动下载的,但是有时候就是不会,很诡异,只能自己手动设置解决方案只需要添加一个shcema文件之后关联.gitlab-ci.yml文件即可1.打开schema编辑2.获取JsonScheme网址gitlabci的jso......
  • Java中的反射(1)——Class类、访问字段、调用方法
            Java中的反射机制是一种强大的工具,它允许程序在运行时动态地检查类的结构、修改对象的属性或调用方法。反射可以打破封装,从而访问类的私有字段或方法,甚至可以在不提前知道类或方法的情况下,动态创建对象并调用它们。我们可以从以下三个方面来详细解析:Class类、......
  • SchoolDB字段创建添加约束以及主键
    --SchoolDB字段创建添加约束以及主键CREATEDATABASESchoolDB;USESchoolDB;CREATETABLEGrade(gradeIdINT(4)NOTNULL,gradeNameVARCHAR(50)NOTNULL,PRIMARYKEY(gradeId));CREATETABLESubject(subjectIdINT(4)NOTNULL,subjectNameVARCHAR(20),classH......
  • 如何调整要素类中的字段顺序?
    一、只做临时调整,保持底层不变的方法1.ArcMap的图层属性表里,可以通过左右拖拽的方式移动字段位置2.ArcMap的图层属性里,找到字段选项卡,可以选中字段上移下移以上两种方式都是临时的,只要把数据重新添加到地图项目中,就会发现字段顺序并没有变化,或者在catalog的数据属性中切换到字......
  • schooldb字段创建添加约束以及主键
    --schooldb字段创建添加约束以及主键创建数据库和表(之前已经创建的部分)CREATEDATABASESchoolDB;USESchoolDB;CREATETABLEGrade(gradeIdINT(4)NOTNULL,gradeNameVARCHAR(50)NOTNULL,PRIMARYKEY(gradeId));CREATETABLESubject(subjectIdINT(4)NOTNULL,......