news 2026/2/7 20:24:51

Groovy对业务能力扩展

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Groovy对业务能力扩展

一、前言

因为之前在项目中使用了Groovy对业务能力进行一些扩展,效果比较好,所以简单记录分享一下,这里你可以了解:

  • 为什么选用Groovy作为脚本引擎

  • 了解Groovy的基本原理和Java如何集成Groovy

  • 在项目中使用脚本引擎时做的安全和性能优化

  • 实际使用的一些建议

二、为什么使用脚本语言

2.1 脚本语言可解决的问题

互联网时代随着业务的飞速发展,不仅产品迭代、更新的速度越来越快,个性化需求也是越来越多,如:多维度(条件)的查询、业务流转规则等。办法通常有如下几个方面:

  • 最常见的方式是用代码枚举所有情况,即所有查询维度、所有可能的规则组合,根据运行时参数遍历查找;

  • 使用开源方案,例如drools规则引擎,此类引擎适用于业务基于规则流转,且比较复杂的系统;

  • 使用动态脚本引擎,例如Groovy,JSR223。注:JSR即 Java规范请求,是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JST,以向Java平台增添新的API和服务。JSR是Java界的一个重要标准。JSR223提供了一种从Java内部执行脚本编写语言的方便、标准的方式,并提供从脚本内部访问Java资源和类的功能,即为各脚本引擎提供了统一的接口、统一的访问模式。JSR223不仅内置支持Groovy、Javascript、Aviator,而且提供SPI扩展,笔者曾通过SPI扩展实现过Java脚本引擎,将Java代码“脚本化”运行。

引入动态脚本引擎对业务进行抽象可以满足定制化需求,大大提升项目效率。例如,笔者现在开发的内容平台系统中,下游的内容需求方根据不同的策略会要求内容平台圈选指定内容推送到指定的处理系统,这些处理系统处理完后,内容平台接收到处理结果再根据分发策略(规则)下发给推荐系统。每次圈选内容都要写一堆对于此次圈选的查询逻辑,内容下发的策略也经常需要变更。所以想利用脚本引擎的动态解析执行,使用规则脚本将查询条件以及下发策略抽象出来,提升效率。

2.2 技术选型

对于脚本语言来说,最常见的就是Groovy,JSR233也内置了Groovy。对于不同的脚本语言,选型时需要考虑性能、稳定性、灵活性,综合考虑后选择Groovy,有如下几点原因:

  • 学习曲线平缓,有丰富的语法糖,对于Java开发者非常友好;

  • 技术成熟,功能强大,易于使用维护,性能稳定,被业界看好;

  • 和Java兼容性强,可以无缝衔接Java代码,可以调用Java所有的库。

2.3 业务改造

因为运营、产品同学对于内容的需求在不断的调整,内容平台圈选内容的能力需要能够支持各种查询维度的组合。内容平台起初开发了一个查询组合为(状态,入库时间,来源方,内容类型),并定向分发到内容理解和打标的接口。但是这个接口已经不能满足需求的变化,为此,最容易想到的设计就是枚举所有表字段(如发布时间、作者名称等近20个),使其成为查询条件。但是这种设计的开发逻辑其实是很繁琐的,也容易造成慢查询;比如:筛选指定合作方和等级S的up主,且对没有内容理解记录的视频,调用内容理解接口,即对这部分视频进行内容理解。为了满足需求,需要重新开发,结果就是write once, run only once,造成开发和发版资源的浪费。

不管是JDBC for Mysql,还是JDBC for MongoDB都是面向接口编程,即查询条件是被封装成接口的。基于面向接口的编程模式,查询条件Query接口的实现可以由脚本引擎动态生成,这样就可以满足任何查询场景。执行流程如下图3.1。

下面给出脚本的代码Demo:

  1. /**

  2. * 构建查询对象Query

  3. * 分页查询mongodb

  4. */

  5. public Query query(int page){

  6. String source = "Groovy";

  7. String articleType = 4; // (source,articleType) 组成联合索引,提高查询效率

  8. Query query = Query.query(where("source").is(source)); // 查询条件1:source="Groovy"

  9. query.addCriteria(where("articleType").is(articleType)); // 查询条件2:articleType=4

  10. Pageable pageable = new PageRequest(page, PAGESIZE);

  11. query.with(pageable);// 设置分页

  12. query.fields().include("authorId"); // 查询结果返回authorId字段

  13. query.fields().include("level"); // 查询结果返回level字段

  14. return query;

  15. }

  16. 复制代码

一键获取完整项目代码

  1. /**

  2. * 过滤每一页查询结果

  3. */

  4. public boolean filter(UpAuthor upAuthor){

  5. return !"S".equals(upAuthor.getLevel(); // 过滤掉 level != S 的作者

  6. }

  7. 复制代码

一键获取完整项目代码

  1. /**

  2. * 对查询结果集逐条处理

  3. */

  4. public void handle(UpAuthor upAuthor) {

  5. UpAthorService upAuthorService = SpringUtil.getBean("upAuthorService"); // 从Spring容器中获取执行java bean

  6. if(upAuthorService == null){

  7. throw new RuntimeException("upAuthorService is null");

  8. }

  9. AnalysePlatService analysePlatService = SpringUtil.getBean("analysePlatService"); // 从Spring容器中获取执行java bean

  10. if(analysePlatService == null){

  11. throw new RuntimeException("analysePlatService is null");

  12. }

  13. List<Article> articleList = upAuthorService.getArticles(upAuthor);// 获取作者名下所有视频

  14. if(CollectionUtils.isEmpty(articleList)){

  15. return;

  16. }

  17. articleList.forEach(article->{

  18. if(article.getAnalysis() == null){

  19. analysePlatService.analyse(article.getArticleId()); // 提交视频给内容理解处理

  20. }

  21. })

  22. }

  23. 复制代码

一键获取完整项目代码

理论上,可以指定任意查询条件,编写任意业务逻辑,从而对于流程、规则经常变化的业务来说,摆脱了开发和发版的时空束缚,从而能够及时响应各方的业务变更需求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/5 8:32:32

解决phpstudy_pro 无法启动 MySQL 以及3306被占用的问题

问题说明 首先我们在启动mysql服务的时候&#xff0c;服务无法启动&#xff0c;而且一直重试。 一、是否真的是端口占用 启动 phpstudy_pro&#xff0c;点击 MySQL 的「启动」按钮&#xff0c;若弹出错误提示&#xff1a; MySQL 启动失败&#xff1a;端口 3306 被占用 或 Po…

作者头像 李华
网站建设 2026/1/30 10:15:28

【synchronized 与 ReentrantLock + Condition 的深度对比 Plus版】

Java并发编程&#xff1a;synchronized 与 ReentrantLock Condition 的深度对比——从Monitor队列到惊群效应与精确唤醒前言正文一、每个Java对象天生都能当锁&#xff1f;Monitor的底层结构形象比喻&#xff1a;锁对象就像一个会议室。关键区别&#xff1a;二、synchronized的…

作者头像 李华
网站建设 2026/1/30 12:50:52

基于单片机的智能窗帘控制系统设计与实现

一、设计背景与核心需求 随着智能家居技术的发展&#xff0c;传统窗帘的手动操作已无法满足现代生活对便捷性、舒适性和节能性的需求。高层住宅大尺寸窗帘拉动费力、忘记关窗导致风雨侵入、光照过强影响室内环境等问题频发。基于单片机的智能窗帘控制系统&#xff0c;通过环境感…

作者头像 李华
网站建设 2026/2/7 5:43:51

Java 应用提供对接第三方接口的优雅高级写法

一、真正的高手,不是“调通接口”,而是“设计边界” 对接第三方接口,看似只是发个请求、拿个 JSON,但背后其实是——系统边界的协作与防御设计。 你面对的不是自己可控的代码,而是一个随时可能“变脸”的外部世界: 对方文档写着“此字段必传”,实际却返回 null 测试环境…

作者头像 李华
网站建设 2026/2/5 7:30:08

基于S7 - 1200 PLC的工业冷库等控制系统漫谈

基于S7-1200 PLC工业冷库控制系统 基于PLC的空调控制系统设计。 基于PLC的工业空调机组设计。基于PLC的冷风机组系统设计带解释的梯形图接线图原理图图纸&#xff0c;io分配&#xff0c;组态画面在工业领域&#xff0c;对于温度的精准控制至关重要&#xff0c;无论是冷库、空调…

作者头像 李华
网站建设 2026/1/30 9:45:28

鸿蒙Electron应用商业化效果评估:数据驱动的增长闭环

基于前文对商业化落地的探讨&#xff0c;本次将聚焦“鸿蒙Electron应用商业化效果评估体系”&#xff0c;从“核心指标构建、数据采集分析、优化迭代闭环”三个维度&#xff0c;提供可量化、可落地的评估方案&#xff0c;帮助开发者精准判断商业化健康度并高效优化。 鸿蒙Elect…

作者头像 李华