我发布了一个自认为很厉害的 Java 参数校验组件,它几乎可以满足所有的参数校验场景,请各位 V 友发表一些看法

225 天前
 sticki

如题,组件名为 “SpEL Validator”,下面我会进行一些介绍,希望各位看完后可以发表一些看法。

「 SpEL Validator 」是基于 SpEL 的参数校验包,也是 javax.validation 的扩展增强包,用于简化参数校验。

解决了什么问题?

我认为的特点

使用方式

性能上我目前还没有进行测试,但代码里使用了很多的反射,会有一定的损耗,后面我准备多加一些缓存,尽量降低性能上的影响。

大概就是这样

以上是关于这个组件的大概介绍,希望各位大佬能够对此发表一些看法,好或者不好都可以发表,感谢各位~

感兴趣的朋友也可以到 GitHub 或者掘金查看详细情况。

GitHub 地址: https://github.com/stick-i/spel-validator

我在掘金发布的详细说明文章: https://juejin.cn/post/7365698962531401766

6800 次点击
所在节点    Java
21 条回复
jwj
225 天前
下次一定用
HojiOShi
225 天前
我虽然不是搞后端这方向的,不过 java 一定有很多同类的库,你的这个和已有的库相比有什么优势吗?看到测试也没有写,怎么让人放心用到生产环境中去呢?
sticki
225 天前
@HojiOShi
1. 目前没有找到功能和我这个一样的库,它的优势就是我上面写到的 “解决了什么问题” 部分
2. 目前确实没有写测试用例,只有少数的使用示例在一个单独的项目中,这块确实需要补充,感谢提醒
fkdog
225 天前
就这句:
@SpelNotNull(condition = "#this.switchAudio == true", message = "语音内容不能为空")

我自己定义一个静态方法,ExceptionUtils.throwIf(this.switchAudio, "语音内容不能为空")不就好了?
为什么还要额外引入你一个类库呢,而且借助反射 API 还会降低额外性能。

而且参数校验逻辑是一个很个性化的东西,javax validation 自带的满足最通用的足矣。
watzds
225 天前
IDE 查看使用、重构之类不友好吧
firecooloo1024
225 天前
其实没必要,记这么多规则增加负担。试试这样写:
```java
@Data
public class UserVo {

private String username;
private Integer age;
private List<String> hobby;

@AssertTrue
public boolean isValid() {
return StringUtils.isNotEmpty(username)
&& age > 0
&& age < 100
&& !hobby.isEmpty();
}
}
```
sticki
225 天前
@fkdog 当然可以自己写代码实现,如果愿意的话,javax validation 也可以不用。4G 普及之前,大家也觉得没必要,我认为这是一样的道理。

至于反射降低的性能,对于一个接口请求来说,只是九牛一毛罢了,框架带来的便利性,往往都会牺牲一定的性能,那几毫秒的延迟,在绝大多数场景下,都是不重要的。举个不恰当的例子,Spring 内也包含了大量的反射,但没人在乎。

再说说个性化,这套组件就是为了解决个性化的参数校验而生的,它几乎可以满足任何个性化的参数校验。
sticki
225 天前
@firecooloo1024 我也这样写过,没什么毛病,就是代码略多一点。这套组件的规则并不复杂,其实和 javax validation 那些注解差不了多少,唯一需要学习的是 SpEL 的语法,但其实也很简单。
sticki
225 天前
@watzds 对,这是一个问题,我给字段使用了 @Language("SpEL"),但 idea 只能识别部分,这很奇怪。未来或许会通过插件的形式辅助开发者使用这套组件,从而解决这个问题。
firecooloo1024
225 天前
@sticki 一般常用注解加字段上就够了,只有你说的枚举、字段联合、复杂校验等才单独写个 is 方法校验,校验逻辑集中,逻辑清晰,没有心智负担,就多了个自定义方法而已,太纯粹的贫血模型也不怎么好。你那个当做学习还行,生产不敢用,哈哈哈嗝
LeegoYih
225 天前
这么写有点恐怖
xwayway
225 天前
condition 和 assertTrue 里面调用属性、方法 全是字符串,对于重构很不友好。
justNoBody
225 天前
我觉得给出来的例子不是很好。

多字段联合校验中,`contentType=1`和`contentType=2`其实是两个不同的业务,如果用了您的`SpEL Validator`,这个业务校验逻辑就放到了`POJO`中。

我个人认为最好是放到业务实现中,以免产生不必要的耦合。
yihy8023
225 天前
给你点赞~感觉作为 javax.validation 额外的补充包不错。
个人觉得楼主直接用 condition 表达式灵活度太高了,里面的规则很难控制复杂度,把它作为保底手段,并且不要写复杂规则还行。condition 用成表达式会导致失去了 java 静态编译的检查,使错误从编译期便到了运行时,并且还要调用才能触发错误,危险程度太高了。假设你改了个字段名,对应的 condition 没改,上到生产后,客户一使用,才发现报错,你慌不慌。
最后提个建议 在启动时扫描注解,把注解的表达式都编译一遍缓存下来,至少问题能在启动时发现。
zmal
225 天前
点赞!
但 java 现在几乎是一个纯工业语言,灵活性相比 其他新兴语言差一些。在 java 里追求灵活性的各种魔法,反而会抛弃 java 相对严谨的语言特性。过于复杂的 SpEL 表达式不是一个很好的方案。
sticki
225 天前
@xwayway 这个问题我在 #9 回复过,实际上 idea 可以识别 SpEL 表达式,识别后字符串会有引用的效果,但目前我的组件对这个识别功能还不完全兼容
sticki
225 天前
@yihy8023 @zmal 对的,简单的规则还行,复杂的规则建议写成静态方法然后在表达式里调用,涉及业务数据的校验还是写在 service 层会更好。

另外,静态编译的检查确实是一个问题,启动时扫描并编译感觉有点困难,参考 mybatis ,或许可以通过插件的形式来解决。
chent114514
223 天前
那我要是来个 ipv6 规则校验呢
fengpan567
222 天前
手写 spel 。。。
sticki
222 天前
@chent114514 嘿,兄弟,注意我提的第三个示例,复杂逻辑校验,可以调用静态方法。你写一个 ipv6 的校验规则,然后在表达式里调用它就好了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1038159

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX