介绍
出发点
在日常开发中经常需要对方法的入参做校验,特别是在远程调用的方法中。
我基于这个需求便开发了这款工具,可以节省在这方面所花费的精力,通过配置的注解,在编译期
对语法树进行修改,就能为方法加入参数的校验逻辑。
知道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<String, Object> 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<String> extra;
public Info() {
}
Info(String name, Double price) {
this.name = name;
this.price = price;
}
}
}
其中的 Args
和 Info
在经过编译后将会根据定义的注解生成校验方法。
static class Info {
String name;
Double price;
List<String> 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<String, Object> 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
<dependencies>
<dependency>
<groupId>io.github.moyada</groupId>
<artifactId>medivh</artifactId>
<version>1.2.0</version>
<scope>provided</scope>
</dependency>
<dependencies/>
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 compile
或 gradle 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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。