资讯专栏INFORMATION COLUMN

方法入参校验工具

xushaojieaaa / 2392人阅读

摘要:介绍出发点在日常开发中经常需要对方法的入参做校验,特别是在远程调用的方法中。类字段无参方法方法参数为或数组或集合类型提供长度或大小校验。类非静态方法方法参数指定参数校验失败时抛出异常。方法方法参数禁用校验逻辑。

介绍 出发点

在日常开发中经常需要对方法的入参做校验,特别是在远程调用的方法中。

我基于这个需求便开发了这款工具,可以节省在这方面所花费的精力,通过配置的注解,在编译期对语法树进行修改,就能为方法加入参数的校验逻辑。

知道Lombok的同学肯定不少吧,其实原理都是一样的。

功能

现在所支持的校验有数字、字符串、数组、集合和Map,并且能够在校验失败时选择是抛出异常或返回数据。

下面让我们直接先看下使用效果吧。

public class MyApp {

    @Throw
    public Info run(Args args,
                    @Nullable Info info,
                    @Return({"test", "0"}) @NotBlank String name,
                    @Return("null") @NumberRule(min = "1") int num) {
        // process
        System.out.println("run");
        return new Info();
    }
}

如上代码,经过编译后将会是这样的 :

public class MyApp {
    public MyApp() {
    }
    public MyApp.Info run(MyApp.Args args, MyApp.Info info, String name, int num) {
        if (args == null) {
            throw new IllegalArgumentException("Invalid input parameter, cause args is null");
        } else {
            String mvar_0 = args.invalid0();
            if (mvar_0 != null) {
                throw new IllegalArgumentException("Invalid input parameter, cause " + mvar_0);
            } else {
                if (info != null) {
                    mvar_0 = info.invalid0();
                    if (mvar_0 != null) {
                        throw new IllegalArgumentException("Invalid input parameter, cause " + mvar_0);
                    }
                }

                if (name == null) {
                    return new MyApp.Info("test", (Double)null);
                } else if (Util.isBlank(name)) {
                    return new MyApp.Info("test", (Double)null);
                } else if (num < 1) {
                    return null;
                } else {
                    System.out.println("run");
                    return new MyApp.Info();
                }
            }
        }
    }
}

原始的逻辑 System.out.println("run"); new Info(); 被放置在了最后,当调用时参数校验都通过后才会执行。
其实例子中的代码省略了对参数定义校验注解的部分,这些类在经过编译器后将会生成参数的校验方法。。。完整的代码如下

public class MyApp {

    @Throw
    public Info run(Args args,
                    @Nullable Info info,
                    @Return({"test", "null"}) @NotBlank String name,
                    @Return("null") @NumberRule(min = "1") int num) {
        // process
        System.out.println("run");
        return new Info();
    }

    class Args {

        @NumberRule(max = "1000") int id;

        @NotNull HashMap param;

        @Nullable @SizeRule(min = 5) boolean[] value;
    }

    static class Info {

        @SizeRule(min = 50) String name;

        @Nullable @NumberRule(min = "-25.02", max = "200") Double price;

        @SizeRule(min = 10, max = 10) List extra;

        public Info() {
        }

        Info(String name, Double price) {
            this.name = name;
            this.price = price;
        }
    }
}

其中的 ArgsInfo 在经过编译后将会根据定义的注解生成校验方法。

   static class Info {
       String name;
       Double price;
       List extra;

       public Info() {
       }

       Info(String name, Double price) {
           this.name = name;
           this.price = price;
       }

       public String invalid0() {
           if (this.name == null) {
               return "name is null";
           } else if (this.name.length() < 50) {
               return "name.length() less than 50";
           } else if (this.price != null && this.price > 200.0D) {
               return "price great than 200.0";
           } else if (this.extra == null) {
               return "extra is null";
           } else {
               return this.extra.size() != 10 ? "extra cannot equals 10" : null;
           }
       }
   }

   class Args {
       int id;
       HashMap param;
       boolean[] value;

       Args() {
       }

       public String invalid0() {
           if (this.value != null && this.value.length < 5) {
               return "value.length less than 5";
           } else if (this.id > 1000) {
               return "id great than 1000";
           } else {
               return this.param == null ? "param is null" : null;
           }
       }
   }

看到这儿,你应该对这个工具的基本功能有了大概的了解,下面我会介绍如果使用这个工具。

使用说明 1.添加依赖

Maven


    
        io.github.moyada
        medivh
        1.2.0
        provided
    

Gradle

dependencies {
  compileOnly "io.github.moyada:medivh:1.2.0"
}

如果没有使用构建工具也没问题,可以从网上下载jar包,一样配置,在后面用 javac -cp 编译就好了。

2. 配置注解

现在可供使用的注解有这几种,支持以类、枚举、接口作为参数添加校验规则。

注解 作用域 作用
@NotNull 类字段、无参方法、方法参数 为对象类型的字段或返回值提供非空校验,默认定义了规则都会进行非空校验。
@Nullable 类字段、无参方法、方法参数 不进行非空校验。
@NotBlank 类字段、无参方法、方法参数 对 String 类型提供不可为空白字符串检测。
@SizeRule 类字段、无参方法、方法参数 为 String 或 数组 或 集合 类型提供长度或大小校验。
@NumberRule 类字段、无参方法、方法参数 为基础数字类型提供大小校验。
@Throw 类、非静态方法、方法参数 指定参数校验失败时抛出异常。
@Return 非静态方法、方法参数 指定参数校验失败时返回数据。
@Exclusive 方法、方法参数 禁用校验逻辑。
@Variable 非静态方法、类 修改当前作用域下校验逻辑产生的变量名和方法名。

例如我需要提供一个判断String是否为null或空白字符串的方法。

@Return("true")
public boolean isEmpty(@NotBlank String str) {
    return false;
}
3. 编译项目

使用构建工具的编译命令, 如 mvn compilegradle build

或者使用 Java 命令进行编译,如 javac -cp medivh.jar MyApp.java

如上述代码,经过编译期后,即可生成方法逻辑,并且创建一个 io.moyada.medivh.support.Util 类提供检验是否为空白字符串的方法,当然也支持自己指定方法。

public boolean isEmpty(String str) {
    if (str == null) {
        return true;
    } else {
        return Util.isBlank(str);
    }
}
结尾

看完这份介绍,如果有兴趣的同学还可以前往 github 查看,会有更详细的文档和示例,欢迎大家进行使用和提出意见。

github.com/moyada/medivh

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72828.html

相关文章

  • 给研发工程师的代码质量利器 | SOFAChannel#5 直播整理

    摘要:接入分为两部分,其一是可视化编辑器,在官网上我们可以获取该编辑器的安装包,并通过的插件管理进行安装。借助可视化编辑器,在整个过程中我们可以替换大部分手工编写代码的工作,进行一站式操作。,有趣实用的分布式架构频道。本文根据 SOFAChannel#5 直播分享整理,主题:给研发工程师的代码质量利器 —— 自动化测试框架 SOFAActs。回顾视频以及 PPT 查看地址见文末。欢迎加入直播互动钉...

    ivan_qhz 评论0 收藏0
  • 不用写代码,也能做好接口测试

    摘要:接口测试形式单个接口测试包含性能测试和通过接口调用进行场景测试。充分来说就是接口测试相对容易实现自动化持续集成。 本文你将了解到 1、接口测试基本概念,包含什么是接口,什么是接口测试,为什么要做接口测试2、接口测试用例设计3、怎样不用写代码,也能快速的根据开发的API文档完成接口自动化测试脚本 注:如果你对接口基本概念和接口测试用例已熟悉,可以直接跳过,其实看一遍也无防,就当作 温故知...

    idisfkj 评论0 收藏0
  • @Validated和@Valid的区别?校验级联属性(内部类)

    摘要:毕竟永远相信本文能给你带来意想不到的收获使用示例关于数据校验这一块在中的使用案例,我相信但凡有点经验的程序员应该没有不会使用的,并且还不乏熟练的选手。 每篇一句 NBA里有两大笑话:一是科比没天赋,二是詹姆斯没技术 相关阅读 【小家Java】深入了解数据校验:Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validati...

    Winer 评论0 收藏0
  • SpringMVC学习笔记

    摘要:是目前最流行的一种互联网软件架构。协议,是一个无状态协议,即所有的状态都保存在服务器端。而这种转化是建立在表现层之上的,所以就是表现层状态转化。具体说,就是协议里面,四个表示操作方式的动词。 一、SpringMVC概述 Spring为展现层提供的基于MVC设计理念的优秀的Web框架,是目前最主流的MVC框架之一 Spring3.0之后全面超越Struts2,成为最优秀的MVC框架 S...

    roundstones 评论0 收藏0
  • 从深处去掌握数据校验@Valid的作用(级联校验

    摘要:如果说要使用数据校验,我十分相信小伙伴们都能够使用,但估计大都是有个前提的环境。具体使用可参考小家让支持对平铺参数执行数据校验默认使用只能对进行校验级联校验什么叫级联校验,其实就是带校验的成员里存在级联对象时,也要对它完成校验。 每篇一句 NBA里有两大笑话:一是科比没天赋,二是詹姆斯没技术 相关阅读 【小家Java】深入了解数据校验:Java Bean Validation 2.0(...

    BlackFlagBin 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<