架构(十四)动态Groovy脚本

一、引言

        最近作者的平台项目需要实现前端输入脚本,后端在用户设置好的一些情况下运行这段脚本。后端是java,所以我们采用Groovy脚本。

        所以要实现的功能就是动态的Groovy脚本!

二、Groovy介绍

        了解groovy和python的就可以直接到第三章了

2.1 优缺点

        Groovy是一种基于Java虚拟机(JVM)的动态编程语言,它结合了静态类型语言和动态类型语言的特性。下面是Groovy的一些优点和缺点:


优点:
1、与Java的无缝集成

        Groovy可以直接在Java代码中使用,与Java代码可以互相调用。这种无缝集成使得在现有Java项目中引入Groovy变得非常容易。


2、动态语言特性

        Groovy支持动态类型、元编程和闭包等特性,使得代码编写更加灵活和简洁。它提供了更简洁的语法和更少的样板代码,提高了开发效率。


3、丰富的语法特性

        Groovy提供了许多便利的语法特性,如集合操作、字符串处理、正则表达式等。它还支持DSL(领域特定语言)的编写,使得代码更易读、更具表达力。


4、可读性强

        Groovy的语法设计力求简洁、易读,使得代码更加清晰和易于理解。它具有更少的冗余代码和更自然的表达方式。


缺点:
1、性能

        相对于Java,Groovy的执行速度可能会慢一些。这是由于动态类型和动态特性的引入,以及Groovy的动态编译过程所导致的。然而,对于大多数应用程序而言,Groovy的性能仍然足够好。


2、工具和库支持

        相对于Java,Groovy的工具和库生态系统相对较小。虽然Groovy可以直接使用Java的库,但有些库可能没有专门为Groovy进行优化或提供更高级的Groovy API。

2.2  Groovy和Python比较

        Groovy和Python都是流行的动态编程语言,它们有一些相似之处,但也有一些区别。下面是Groovy和Python之间的一些比较


1、语法和风格


        Groovy的语法与Java非常相似,因此对于Java开发者来说,学习和使用Groovy相对容易。它也支持类似Java的面向对象编程风格。
        Python的语法更加简洁和优雅,具有非常清晰的语法结构。它采用了缩进来表示代码块,使得代码更易读。


2、类型系统


        Groovy是一种动态类型语言,它允许变量在运行时动态地改变其类型。这使得Groovy更加灵活,但也可能导致一些类型相关的错误。
        Python也是一种动态类型语言,但它具有更严格的类型系统。Python 3引入了类型提示(Type Hints)的功能,可以在代码中指定变量的类型,提高了代码的可读性和可维护性。


3、生态系统和库支持


        Python拥有非常庞大和活跃的生态系统,有大量的第三方库和工具可供使用。这使得Python成为数据科学、Web开发、自动化脚本等领域的首选语言。
        Groovy的生态系统相对较小,但它可以直接使用Java的库。对于Java开发者来说,Groovy可以无缝集成到Java项目中,享受Java生态系统的优势。


4、性能


        通常情况下,由于其动态特性,Groovy的执行速度可能比Python慢一些。然而,对于大多数应用程序而言,这种差异并不明显,因为它们通常受限于I/O等其他因素。
        Python通常被认为是一种相对较慢的语言,但通过使用C扩展和优化技术,可以提高Python的性能。


5、用途和应用领域


        Python在数据科学、人工智能、Web开发、自动化脚本等领域具有广泛的应用。它拥有丰富的库和工具,如NumPy、Pandas、Django等,使得开发更加便捷。
        Groovy在Java开发领域应用广泛,特别适用于构建DSL(领域特定语言)、编写脚本和快速原型开发。

三、动态脚本

1、pom

<dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy</artifactId><version>3.0.8</version></dependency>

2、前端

        既然是动态的,就需要用户随意填写,即使有限制也是在后端进行权限之类的限制,然后向用户说明使用规则给用户提供一些基础类

        所以前端只要给一个输入脚本的内容框就好

3、后端

3.1 运行groovy脚本

        用户的脚本其实就是一个字符串,要运行这段字符串,怎么实现?

        作者使用的是GroovyShell,看起来很简单,但是这只是开始,随着后面的拓展需要考虑很多细节

String script = param.getContent();// 创建GroovyShellGroovyShell shell = new GroovyShell();// 运行Groovy脚本Object response = shell.evaluate(script);

3.2 传入参数给脚本       

        第一个要考虑的就是一些参数可能是前面的逻辑带过来的,比如操作类型、订单、费用之类的,那就需要把这些参数带给脚本

        // 创建绑定变量Binding binding = new Binding();binding.setVariable("orderId", orderId);binding.setVariable("parameter", parameter);// 创建GroovyShellGroovyShell shell = new GroovyShell(binding);// 运行Groovy脚本Object response = shell.evaluate(script);

3.2 基础工具

        脚本是要用来做逻辑的,不可能每次都是前面的逻辑把数据准备好,然后传递给脚本计算。

        所以要把一些基础功能包装好,比如查数据库、调用接口

        查数据库就用到之前的一篇文章了,通过动态的多数据源暴露出一个工具类,让脚本拿到这个类,指定数据库和sql就可以进行查询:

架构(十)Mybatis动态数据源及其原理_mybatis 动态数据源-CSDN博客

@Component
public class CommonGateWayImpl implements CommonGateWay {@Resourceprivate CommonQueryMapper commonQueryMapper;@Overridepublic List<HashMap> executeSql(String db, String sql) {DataSourceThreadLocal.setDB(db);List<HashMap> res = commonQueryMapper.query(sql);DataSourceThreadLocal.clearDB();return res;}
}

        调用接口基本上每家公司都不太一样,但是原理是相似的,都是根据系统标识找到一个可用的节点,拿到节点的url,调用这个url+方法,把请求参数转json作为消息体传过去

        所以调用接口的工具类至少要有这两个方法,合并成一个也行,需要跟自己公司的注册中心打通一下,让中间件团队提供查询节点的功能。然后如果有权限校验的也要开一下,免得调用不通。

@Component
public class ExecuteInterfaceUtil {public String getUrl(String systemCode, String action) {List<UrlEntity> urlList = //查系统所有节点if (CollectionUtilsExt.isBlank(urlList)) {return null;}String url = urlList.size() > 0 ? urlList.get(0).getUrl() : "";url = url + action;return url;}public String execute(String url, String body, HashMap parameter)  {// 发送Http请求return response;}
}

3.3 SpringBoot取Bean

        也是在写脚本执行的时候发现还需要一个功能,就是从SpringBoot的bean工厂取Bean,不然自己new一个对象是调用不了这里面的方法的,而且new也不优雅,这是基础工具又不是数据包装

        所以就要找一下实现的方法,其实经常用的功能

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;@Component
public class SpringUtil implements ApplicationContextAware {// 应用上下文环境private static ApplicationContext context;@SuppressWarnings("static-access")@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {context = applicationContext;}public static ApplicationContext getContext() {return context;}/*** 根据bean name 获取对象** @param name* @return*/public static <T> T getBean(String name) {return (T)context.getBean(name);}/*** 根据Class获取对象* * @param clazz* @param <T>* @return* @throws BeansException*/public static <T> T getBean(Class<T> clazz) throws BeansException {return context.getBean(clazz);}
}

4、脚本

        底层都准备好了,那就可以写脚本试一试了,包名和导入的工具类路径都是必须的,groovy执行的时候都需要导入

        这里演示了一下查完db数据之后,再去查接口明细

package ***.groovyimport ***.JSONUtil
import ***.StringUtilsExt
import ***.SpringUtil
import ***.ExecuteInterfaceUtil
import ***.CommonGateWay
import org.apache.curator.shaded.com.google.common.collect.ListsCommonGateWay commonGateWay = SpringUtil.getBean(CommonGateWay.class)
ExecuteSoaUtil executeInterfaceUtil = SpringUtil.getBean(ExecuteSoaUtil.class)
List<HashMap> dataList = commonGateWay.executeSql("orderDb", "SELECT TOP 10 orderId FROM order ORDER BY update_time DESC;")
if (dataList == null || dataList.size() == 0) {return dataList
}
String url = executeInterfaceUtil.getUrl("abc", "getDetail")
if (url == null || url.length() == 0) {return dataList
}
List<HashMap> res = new ArrayList<>()
for (HashMap map : dataList) {HashMap body = new HashMap(2)body.put("orderIdList", Lists.newArrayList(map.get("orderid")))String response = executeInterfaceUtil.execute(url, JSONUtil.toJson(body), null)if (StringUtilsExt.isBlank(response)) {return res}HashMap<String, Object> interfaceMap = JSONUtil.parse(response, HashMap.class)res.add(soaMap)for (Map.Entry<String, Object> entry : interfaceMap.entrySet()) {Object value = entry.getValue()if (!(value instanceof Integer) && !(value instanceof String)) {entry.setValue(JSONUtil.toJsonNoException(value))}}if (!interfaceMap.containsKey("responseCode") || (int) interfaceMap.get("responseCode") != SUCCESS) {return res}
}
return res

        再看看执行结果

 四、总结

        动态的脚本这样就实现了,其实用python也可以,java也有支持python的执行库,不过用起来就有点曲折了。

        即使用得是和java无缝集成的Groovy,过程也是有点绕弯的,而且还有一些小坎没写,写出来会降低作者的逼格,毕竟很多时候调试开发遇到的都是一些很小的问题一下子没转过来,事后想想又觉得脑子丢了一会。

        有兴趣的同学可以在评论区和作者讨论自己项目的疑难杂症!一起交流进步

                

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/692959.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QGis软件 —— 7、QGis - 绘制操作多边形、多边形与线条互转、多边形经纬度导出csv文件

绘制操作多边形 1、绘制多边形&#xff08;下面附上结果及操作过程&#xff09; 结果如下&#xff1a; 具体操作&#xff1a; 2、对多边形加入字段信息并显示&#xff08;下面附上结果及操作过程&#xff09; 结果如下&#xff1a; 具体操作&#xff1a; 多边形与线条互转 …

加载arcgis切片服务网络请求有大量404错误

需求&#xff1a; 前端访问arcgis切片服务时&#xff0c;在网络请求中出现大量404&#xff08;Not Found&#xff09;错误&#xff0c;切片时设置了感兴趣区域&#xff0c;在感兴趣范围内请求切片时能够正常返回切片。 问题分析&#xff1a; 设置感兴趣区域切片的目的是减少站…

【 JS 进阶 】异常处理与 debugger 调试

异常处理 了解 JavaScript 中程序异常处理的方法&#xff0c;提升代码运行的健壮性。 throw 异常处理是指预估代码执行过程中可能发生的错误&#xff0c;然后最大程度的避免错误的发生导致整个程序无法继续运行 总结&#xff1a; throw 抛出异常信息&#xff0c;程序也会终止…

AD24-开窗

一、PCB阻焊开窗处理 开窗效果图 1、将铜皮选中&#xff0c;复制&#xff0c;来到阻焊层&#xff0c;利用特殊粘贴 2、如出现报错&#xff0c;可利用实心填充在阻焊层进行重新绘制&#xff1b;在3D状态下进行查看 3、放置一块填充&#xff1b;称为露基材&#xff08;PCB材料&am…

QT常用事件

鼠标事件&#xff08;QMouseEvent&#xff09;&#xff0c;如点击、移动、释放等。 键盘事件&#xff08;QKeyEvent&#xff09;&#xff0c;如按键按下和释放。 窗口事件&#xff08;QResizeEvent, QMoveEvent&#xff09;&#xff0c;当窗口大小或位置改变时。 绘制事件&…

内网穿透与搭建私人服务器

前言 内网穿透是一种技术&#xff0c;允许用户从外部网络访问内部私有网络中的服务器或设备。这对于想要从任何地方访问家中或办公室内部网络资源的用户非常有用。以下是为初学者准备的关于如何实现内网穿透以及搭建自己的私人服务器的详细指南。 在这个数字化时代&#xff0c;…

弱网演练的小插曲记录

文章目录 1. 写在最前面1.1 关于弱网1.2 关于插曲 2. 模拟弱网的工具2.1 tc2.1.1 原理2.1.2 使用 2.2 blade2.2.1 原理2.2.2 使用 3. tc vs iptable4. 碎碎念5.参考资料 1. 写在最前面 节前在做历史故障演练的 1:1 复现&#xff0c;以验收当前新增的监控告警可以覆盖历史的故障…

python之ftp小工具

文章目录 python之FTP小工具 python之FTP小工具 源码 #!/usr/bin/python3 import os import sys from pyftpdlib.authorizers import DummyAuthorizer from pyftpdlib.handlers import FTPHandler, ThrottledDTPHandler from pyftpdlib.servers import FTPServer import logg…

CP03大语言模型ChatGLM3-6B特性代码解读(1)

CP03大语言模型ChatGLM3-6B特性代码解读&#xff08;1&#xff09; 文章目录 CP03大语言模型ChatGLM3-6B特性代码解读&#xff08;1&#xff09;总述提示词及UI交互基础conversation.py提示词相关角色Role的处理对话内容字符里的提示词处理 对话基础client.py模型路径等参数设置…

HTTPS(超文本传输安全协议)被恶意请求该如何处理。

HTTPS&#xff08;超文本传输安全协议&#xff09;端口攻击通常是指SSL握手中的一些攻击方式&#xff0c;比如SSL握手协商过程中的暴力破解、中间人攻击和SSL剥离攻击等。 攻击原理 攻击者控制受害者发送大量请求&#xff0c;利用压缩算法的机制猜测请求中的关键信息&#xf…

防火墙——计算机网络

前述基于密码的安全机制不能有效解决以下安全问题&#xff1a; 用户入侵&#xff1a; 利用系统漏洞进行未授权登录&#xff1b; 授权用户非法获取更高级别权限等。 软件入侵&#xff1a; 通过网络传播病毒、蠕虫和特洛伊木马。 拒绝服务攻击等。 解决方法&#xff1a; 防火墙&a…

LabVIEW压电驱动迟滞补偿控制

LabVIEW压电驱动迟滞补偿控制 随着精密控制技术的迅速发展&#xff0c;压电陶瓷驱动器因其高精度和快速响应特性&#xff0c;在微纳精密定位系统中得到了广泛应用。然而&#xff0c;压电材料固有的迟滞非线性特性严重影响了其定位精度和重复性。开发了一种基于LabVIEWFPGA的压…

Hive数据仓库行转列

查了很多资料发现网上很多文章都是转发和抄袭&#xff0c;有些问题。这里分享一个自己项目中使用的行转列例子&#xff0c;供大家参考。代码如下&#xff1a; SELECTmy_id,nm_cd_map[A] AS my_cd_a,nm_cd_map[B] AS my_cd_b,nm_cd_map[C] AS my_cd_c,nm_num_map[A] AS my_num_…

MySQL安装教程(详细版)

今天分享的是Win10系统下MySQL的安装教程&#xff0c;打开MySQL官网&#xff0c;按步骤走呀~ 宝们安装MySQL后&#xff0c;需要简单回顾一下关系型数据库的介绍与历史&#xff08;History of DataBase&#xff09; 和 常见关系型数据库产品介绍 呀&#xff0c;后面就会进入正式…

C语言OJ题——1091装箱问题

装箱问题 1.题目2.解题思路3.代码实现4.细节补充说明 1.题目 题目描述 一个工厂生产的产品形状都是长方体&#xff0c;高度都是h&#xff0c;主要有1 * 1&#xff0c;2 * 2&#xff0c;3 * 3&#xff0c;4 * 4&#xff0c;5 * 5&#xff0c;6 * 6等6种。这些产品在邮寄时被包装…

Java使用Redis实现分页功能

分页功能实现应该是比较常见的&#xff0c;对于redis来说&#xff0c;近期刷题就发现了lrange、zrange这些指令&#xff0c;这个指令怎么使用呢&#xff1f; 我们接下来就来讲解下。 目录 指令简介lrangezrange Java实现Redis实现分页功能 指令简介 lrange lrange 是 Redis 中…

Cesium for Unreal 从源码编译到应用——插件编译

一、安装环境 Unreal Engine 5.3 CMake 3.17.5 Microsoft Visual Studio 2019 二、源码准备 下载cesium-unreal-samples工程。 git clone https://github.com/CesiumGS/cesium-unreal-samples.git 然后在工程目录创建Plugins文件夹&#xff0c;并下载cesium-unreal工程。 …

keepalived双主模式测试

文章目录 环境准备部署安装keepavlived配置启动测试模拟Nginx宕机重新启动问题分析 环境准备 测试一下keepalived的双主模式&#xff0c;所谓双主模式就是两个keepavlied节点各持有一个/组虚IP&#xff0c;默认情况下&#xff0c;二者互为主备&#xff0c;同时对外提供服务&am…

ubuntu系统个人部署LangChain过程

官方教程&#xff0c;github和huggingface都需要梯子&#xff1a; 开发环境部署 chatchat-space/Langchain-Chatchat Wiki (github.com) 具体参考官方的&#xff0c;这里额外记录一下官方文档里面没有写的。 安装前&#xff0c;确保openSSL版本是新的 查看当前环境下是否有…

从宏观到微观——泽攸科技ZEM系列台式扫描电子显微镜在岩石分析中的应用

岩石作为地球地壳的主要构成物质之一&#xff0c;其微观结构对于了解地质过程、资源勘探以及工程建设具有重要意义。按照岩石的成因&#xff0c;可以把它们分为三类&#xff1a;岩浆岩、沉积岩和变质岩。在地球表面&#xff0c;沉积岩占据75%的份额&#xff0c;而在地壳深度&am…