当前位置: 首页 > news >正文

同事嫌参数校验太丑?我掏出 SpEL Validator + IDEA 插件,直接让他闭嘴

参数校验这活儿,写 Java 后端的同学肯定没少干。@NotNull@Size@NotBlank一把梭,搞定大部分场景没啥问题。

但总有一些场景,这些基本注解是真搞不定的。 比如你想根据某个字段的值来决定另一个字段要不要校验,或者校验一个枚举值是不是合法的,再或者校验的时候需要查一下数据库……

遇到这种情况怎么办?要么在 Service 层写一堆 if/else,要么自定义ConstraintValidator,代码散落在各处,改起来还容易漏。

SpEL Validator 是什么?

简单来说,SpEL Validator 是一个基于 Spring Expression Language 的参数校验框架,它不是要替代你熟悉的那些@NotNull@NotBlank,而是在 Jakarta Validation 的基础上做增强,把原来搞不定的那些场景给补上。

用过@NotNull的同学,上手 SpEL Validator 几乎零成本。直接看几个例子感受下:

条件式校验:根据switchAudio的值决定是否校验audioContent,只有当condition的表达式返回true时才会开启校验

@NotNull private Boolean switchAudio; @SpelNotNull(condition = "#this.switchAudio == true", message = "语音内容不能为空") private Object audioContent;

枚举值校验:调用静态方法判断枚举值是否存在,这里是个断言条件,当assertTrue的表达式返回false时校验不通过

@SpelAssert(assertTrue = " T(cn.sticki.enums.ExampleEnum).getByCode(#this.testEnum) != null ", message = "枚举值不合法") private Integer testEnum;

调用 Spring Bean:直接在表达式中调用已注入的 Bean

@SpelAssert(assertTrue = "@exampleService.getUser(#this.userId) != null", message = "用户不存在") private Integer userId;

怎么样,够直观吧?不用再到处翻 Validator 了,打开类就能看到所有的校验规则。

不过,你可能也注意到了——这些 SpEL 表达式是写在字符串里的,这意味着它们没有语法高亮、没有字段补全、字段名拼错了也没人提醒你,得等到运行时才能发现。

但是,注意我要说但是了。

我开发了一个配套的 IDEA 插件:SpEL Validator Support。装上之后,编写 SpEL 表达式也会有语法高亮、智能补全、Ctrl+Click 跳转、重命名同步、错误实时提醒,全都有。

实战演示

准备工作

引入依赖,Spring Boot 3.x 用 jakarta 版:

<dependency> <groupId>cn.sticki</groupId> <artifactId>spel-validator-jakarta</artifactId> <version>Latest Version</version> </dependency>

Spring Boot 2.x 的同学把jakarta换成javax就行。

然后去 IDEA 的 Plugins 里搜索安装SpEL Validator Support插件,重启 IDEA。

案例一:条件式校验 + 智能补全

这是示例项目中最基础的一个场景——SimpleExampleParamVo

@Data @SpelValid public class SimpleExampleParamVo { @NotNull private Boolean switchAudio; @SpelNotNull(condition = "#this.switchAudio == true", message = "语音内容不能为空") private Object audioContent; @SpelAssert(assertTrue = " T(cn.sticki.validator.spel.example.enums.ExampleEnum).getByCode(#this.testEnum) != null ", message = "枚举值不合法") private Integer testEnum; @SpelAssert(assertTrue = "@exampleService.getUser(#this.userId) != null", message = "用户不存在") private Integer userId; }

这个类里就包含了三种之前不好处理的校验场景:switchAudio为 true 时才校验audioContent;通过静态方法校验枚举值是否合法;调用 Spring Bean 查一下用户是否存在。全都写在注解里,没有一行 if/else。

装了插件之后,你会发现 SpEL 表达式有了语法高亮,字段名、方法调用、类型引用都有颜色区分。输入#this.的时候,IDEA 会自动弹出当前类的所有字段。

发起请求看一下校验效果:

// switchAudio=true 但 audioContent 为空 → 校验不通过 {"switchAudio": true, "audioContent": null} // 响应:{"code": 400, "message": "audioContent 语音内容不能为空"} // switchAudio=false → audioContent 不校验,通过 {"switchAudio": false, "audioContent": null} // 响应:{"code": 200, "message": "成功"}

案例二:分组校验 + 引用导航

再看另一个更有意思的例子,根据type分组校验不同的字段。

在某些内容比较多的表单场景下,可能会根据用户选择的不同类型,然后展示不同的字段,这时候就需要根据类型来分组校验不同的字段。

@Data @SpelValid(spelGroups = "#this.type") public class GroupExampleParamVo { @NotNull @Pattern(regexp = "^text|audio$") private String type; @SpelNotNull(group = Group.TEXT) private Object textContent; @SpelNotNull(group = Group.AUDIO) private Object audioContent; @SpelNotNull // 未指定分组时,默认被校验 private Integer other; static class Group { private static final String TEXT = "'text'"; private static final String AUDIO = "'audio'"; } }

type = "text"时,只有textContentother会被校验;当type = "audio"时,只有audioContentother会被校验。分组逻辑写在注解里就完事了,齐活。

有了插件,你可以Ctrl+Click表达式中的字段名,直接跳转到字段定义。也可以在字段上右键Find Usages,查看它在哪些 SpEL 表达式中被引用了。

案例三:调用 Spring Bean

有时候校验逻辑不是简单的判空或比大小,可能需要查一下数据库才能确定参数合不合法。这时候就需要在表达式里调用 Spring Bean 了。

默认情况下,SpEL Validator 不支持调用 Spring Bean,需要先在启动类上加上@EnableSpelValidatorBeanRegistrar注解开启 Bean 支持:

@EnableSpelValidatorBeanRegistrar @SpringBootApplication public class RestApplication { public static void main(String[] args) { SpringApplication.run(RestApplication.class, args); } }

然后在你的 Service 里写个查询方法(这里简单模拟一下):

@Service public class ExampleService { public User getUser(int id) { User user = new User(); user.setId(id); user.setName("阿杆"); return user; } }

现在就可以在校验注解中直接引用这个 Bean 了:

@SpelAssert(assertTrue = "@exampleService.getUser(#this.userId) != null", message = "用户不存在") private Integer userId;

@exampleService就是 Spring 容器里那个 Bean 的名字,SpEL 原生语法。

这里只是用简单例子演示一下调用方式。实际开发中你可以调用任何已注入的 Bean 方法来做校验,查缓存查数据库都行。当然了,校验里别搞太重的操作,查个缓存差不多得了,别搞成查了三张表还调了两个远程接口😅。

有了插件的加持,@exampleService同样能被识别和高亮。如果你不小心写错了 Bean 名或字段名,插件也会给你标红提醒。

更多能力速览

除了上面演示的场景,SpEL Validator 还提供了丰富的约束注解:

注解说明对标 Jakarta
@SpelAssert逻辑断言
@SpelNotNull / @SpelNull空值校验@NotNull / @Null
@SpelNotEmpty / @SpelNotBlank非空校验@NotEmpty / @NotBlank
@SpelSize长度校验@Size
@SpelMin / @SpelMax数值范围@Min / @Max
@SpelDigits数字精度@Digits
@SpelFuture / @SpelPast 等时间校验@Future / @Past

所有注解都支持condition(条件开关)和group(分组),也支持国际化消息message = "{key}"即可根据Accept-Language自动切换语言。

如果有自定义约束注解的需求,只要加上@SpelConstraint元注解,IDEA 插件同样能识别并提供智能支持。

最后

OK,差不多就介绍到这里了。总结起来就是:SpEL Validator 负责把校验能力补齐,IDEA 插件负责让你写表达式的时候不再抓瞎,两个搭一起用体验还是很舒服的。

如果你的项目里经常碰到跨字段校验、条件式校验这类场景,不妨试试看,接入成本很低的。

http://www.jsqmd.com/news/411269/

相关文章:

  • C++中的Rule of Five
  • 新手必看!高性价比ELISA试剂盒品牌推荐,省钱又好用 - 包罗万闻
  • 2026黑河工控产品厂商口碑揭秘:哪些品牌值得信赖?中低压电气/施耐德电气/工控产品,工控产品生产厂家哪家好 - 品牌推荐师
  • 理解 SQL JOIN: ON 与 WHERE 的区别
  • feel导入
  • 项目管理工具哪个好?2026年项目管理软件推荐与排名,解决数据孤岛与成本痛点 - 十大品牌推荐
  • 吐血推荐! AI论文软件 千笔·专业学术智能体 VS 云笔AI,MBA写作神器!
  • 「致命漏洞」什么是反序列化漏洞?一篇文章彻底搞懂原理、危害与防御
  • 最简解决idea系列的中文编码问题
  • 反序列化漏洞详解:原理、攻击链与防御,一篇文章彻底搞懂!
  • MySQL性能优化核心:InnoDB Buffer Pool 详解
  • 如何撰写一篇高质量的文献综述
  • 哪款项目管理系统更智能?2026年项目管理系统推荐与评测,解决扩展性痛点 - 十大品牌推荐
  • 照着用就行:专科生专属AI论文网站 —— 千笔·专业论文写作工具
  • 计算机毕设java有家披萨店管理系统的设计与实现 基于Java的意式餐饮门店运营平台开发 披萨连锁企业数字化订餐与后厨调度系统的设计
  • Nlog封装类
  • 深入浅出反序列化漏洞:从PHP到Java,一文掌握核心防御技巧
  • 计算机毕设java在线视频网站设计与实现 基于Java的流媒体点播平台开发与实现 SpringBoot架构下的网络视频服务系统构建
  • 告别盗版!2026年网络安全从业者必备开源工具全家桶
  • 反序列化漏洞:从“拆包”到“夺命”——攻击链构建与全面防护指南
  • 重磅深度:OpenAI Codex负责人揭秘,为什么我们熟知的“编程”已经结束?
  • 汽车制造工艺开发如何实现智能化与绿色化转型?
  • 【系统分析师】10.0 系统规划与分析
  • 2026变压器回收公司权威榜单 TOP5:技术实力与回收规模综合解析 - 深度智识库
  • 2026|写论文被坑到怀疑人生,唯一救星竟然是它
  • 2026年冷却塔厂家怎么选,解读知名的冷却塔厂家特色 - 工业推荐榜
  • 2005-2025年我国逐日地表温度栅格数据
  • 什么是反序列化漏洞?一篇文章讲清楚
  • 2026年开公司,老板要了解的财税知识
  • 基于javaweb的线上鲜花商城管理系统的设计与实现(11893)