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

Springboot项目中加载Groovy脚本并调用其内部方代码实现

前言

项目中部署到多个煤矿的上,每一种煤矿的情况都相同,涉及到支架的算法得写好几套,于是想到用脚本实现差异变化多的算法!一开始想到用java调用js脚本去实现,因为这个不需要引入格外的包,js对我来说也没啥学习成本,后来发现js的方法的参数中没办法使用java的对象传参。如果要把java对象分解成多个基本类型的参数传递的话,js的代码实现就变复杂和臃肿了。于是改用groovy脚本去实现,后来经过两个小时的实现,终于调通!groovy的语法和java类似,学习成本很低,且groovy可以引入java的类使用java的对象,调用java的方法也很简单,下面给出实现的代码图文教程。

Groovy简介

Groovy是一种基于JVM(Java虚拟机)的动态编程语言,它具有Java的兼容性和许多强大的功能,可以用来快速开发Java应用程序。

以下是Groovy的一些主要特点:

  • 静态类型:Groovy是静态类型的语言,这意味着你可以在编译时检测到许多常见的错误,从而提高代码的质量和可维护性。
  • 动态类型:同时,Groovy也是动态类型的语言,这意味着你可以在运行时动态地改变变量的类型,这使得Groovy代码更加灵活和易读。
  • 强大的语法:Groovy的语法比Java更简洁、更易读。它支持多种编程范式,如面向对象编程和函数式编程。
  • 与Java无缝集成:Groovy可以与Java代码无缝集成,这意味着你可以在Groovy代码中使用Java类库,反之亦然。这使得Groovy成为Java开发者的强大工具。
  • 简洁的语法:与Java相比,Groovy的语法更为简洁。它支持许多Java不支持的特性,如可选的括号、可选的类型声明等。
  • 强大的元编程能力:Groovy具有强大的元编程能力,它允许你在运行时动态地修改代码。这使得Groovy成为快速开发原型或快速实现想法的有力工具。
  • 测试驱动开发:Groovy支持测试驱动开发(TDD),它使得你可以快速编写测试代码并以此驱动你的业务逻辑代码。
  • 闭包:Groovy支持闭包,这是一种可以包含代码块的语法结构,可以作为参数传递给函数,也可以赋值给变量。
  • 运行时类型检查:虽然Groovy是动态类型的语言,但它也支持运行时类型检查,这使得你可以在运行时捕获许多类型错误。
  • AST变换:Groovy允许你直接操作Java字节码,这使得你可以在编译时对代码进行修改。这是许多静态类型语言无法提供的功能。

总的来说,Groovy是一种强大、灵活且易于使用的编程语言,无论你是一个Java开发者还是一个想要使用JVM的语言的人,你都可以从Groovy中受益。

教程

引入依赖

首先在springboot项目中引入groovy的依赖,maven引入配置如下:

        <dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-all</artifactId><version>2.4.11</version></dependency>

java加载使用脚本工具类

新建一个ScriptProvider脚本使用类,代码如下:


import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.io.File;
import java.io.IOException;
import java.util.List;/*** @author Lenovo*/
@Component
@Slf4j
public class ScriptProvider {private GroovyObject groovyObject;@Value("${app.work-face}")private  void loadScript(String name){try (GroovyClassLoader classLoader = new GroovyClassLoader()) {Class<?> groovyClass = classLoader.parseClass(new File("etc/"+name+".groovy"));groovyObject= (GroovyObject) groovyClass.newInstance();} catch (InstantiationException | IOException | IllegalAccessException e) {log.error(e.getMessage());}}public  void overloadScript(String filePath){try (GroovyClassLoader classLoader = new GroovyClassLoader()) {Class<?> groovyClass = classLoader.parseClass(new File(filePath));groovyObject= (GroovyObject) groovyClass.newInstance();} catch (InstantiationException | IOException | IllegalAccessException e) {log.error(e.getMessage());}}public double calStentHeight(int i, List<DataValue> dataValues){Object[] objects = new Object[]{i,dataValues};Object result=groovyObject.invokeMethod("calStentHeight",objects);return Double.parseDouble(result.toString());}public double revisedStentHeight(int i, List<DataValue> dataValues){Object[] objects = new Object[]{i,dataValues};Object result=groovyObject.invokeMethod("revisedStentHeight",objects);return Double.parseDouble(result.toString());}public Object revisedStentStroke(int i, List<DataValue> dataValues) {Object[] objects = new Object[]{i,dataValues};Object result=groovyObject.invokeMethod("revisedStentStroke",objects);return Double.parseDouble(result.toString());}
}

代码解析

  • 在spring配置文件中配置不同的脚本名,通过@Value(“${app.work-face}”) 注解 ,在项目启动时加载对应的groovy脚本文件。
  • invokeMethod(“calStentHeight”,objects); calStentHeight 是groovy脚本中定义的方法,objects数组是groovy脚本中方法的参数,objects数组数组的元素顺序和方法的参数保持一致。
  • new File(“etc/”+name+“.groovy”) 是读入项目根目录下,etc文件夹下的某个groovy脚本文件,打成jar运行的时候,读取的是jar同级目录下,etc文件夹下的某个groovy脚本文件。

在这里插入图片描述

groovy脚本

创建一个groovy脚本,以4703.groovy为例,代码如下:

import org.eclipse.milo.opcua.stack.core.types.builtin.DataValuedef calStentHeight(int i,List<DataValue> dataValues){return dataValues.get(i).getValue().getValue();
}def revisedStentHeight(int i,List<DataValue> dataValues){double d=dataValues.get(i).getValue().getValue();int stentNo=i+1;if(stentNo<=2||stentNo>=92){if(d>3.6){d=3.6;}if(d<=0){d=3.3;}}else{if(d>1.9){d=stentNo==3?1.9:dataValues.get(i-1).getValue().getValue();}if(d<=0){d=1.9;}}return d;
}def revisedStentStroke(int i,List<DataValue> dataValues){double d=dataValues.get(i).getValue().getValue();int stentNo=i+1;if(stentNo<=2||stentNo>=92){if(d>900D){d=900D;}if(d<=0D){d=0D;}}else{if(d>900D||d<=0D){d=dataValues.get(i-1).getValue().getValue();;}}return d;
}

代码解析:

  • DataValue对象是java opc开源工具获取,opc点位对应值返回的对象。
  • groovy的方法内部可以向java一样编写

java调用groovy脚本的方法

在springboot中调用groovy脚本中的方法,示例代码如下:

    @Resourceprivate ScriptProvider scriptProvider;StentsDTO.putStentHeight(key.getPointAddress(),scriptProvider.calStentHeight(i,dataValues));objValue= scriptProvider.revisedStentHeight(i,dataValues);

代码解析

  • 通过@Resource注解将ScriptProvider类注入到spring的容器中,通过ScriptProvider的实例对象,调用内部方法。

groovy脚本修改监听类实现

java无法是实现对具体某个文件操作事件的监听,只能实现文件夹和文件夹下的文件的事件的监听。我们可以通过监听文件夹监听实现对文件的监听。代码如下(代码中只有文件修改事件的监听):


import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.nio.file.*;/*** @author tarzan*/
@Component
@AllArgsConstructor
@Slf4j
public class FileSystemWatcher {private final ScriptProvider scriptProvider;public void modifyWatch(){try {watch(StandardWatchEventKinds.ENTRY_MODIFY);} catch (IOException | InterruptedException e) {log.error(e.getMessage());}}private  void watch(WatchEvent.Kind<Path> eventKind) throws IOException, InterruptedException {// 定义你想要监听的路径Path path = Paths.get("etc");// 创建 WatchServiceWatchService watchService = FileSystems.getDefault().newWatchService();// 将路径注册到 WatchService,并指定你想要监听的事件类型path.register(watchService, eventKind);while (true) {// 获取下一个文件系统事件WatchKey key = watchService.take();for (WatchEvent<?> event : key.pollEvents()) {// 获取事件类型WatchEvent.Kind<?> kind = event.kind();if (kind == StandardWatchEventKinds.OVERFLOW) {continue;}// 获取发生事件的文件WatchEvent<Path> ev = (WatchEvent<Path>) event;Path fileName = ev.context();// 打印出发生事件的文件名和事件类型boolean eventFlag=!fileName.toFile().getName().endsWith("~");if(eventFlag){log.info("etc/"+fileName +" be modified");scriptProvider.overloadScript("etc/"+fileName);}}//睡眠1秒Thread.sleep(1000);// 重置 WatchKey,以便接收下一个事件boolean valid = key.reset();if (!valid) {break;}}}}

代码解析

  • 代码通过监听etc文件,当监听到etc文件夹下的文件进行修改操作或者覆盖操作的事件,就会重新加载修改后的grooy脚本文件。

结语

如果你对文章有疑问或者更好的见解,请在评论区留言!如果文章对你有帮助,请点赞收藏!!!

相关文章:

Springboot项目中加载Groovy脚本并调用其内部方代码实现

前言 项目中部署到多个煤矿的上&#xff0c;每一种煤矿的情况都相同&#xff0c;涉及到支架的算法得写好几套&#xff0c;于是想到用脚本实现差异变化多的算法&#xff01;一开始想到用java调用js脚本去实现&#xff0c;因为这个不需要引入格外的包&#xff0c;js对我来说也没…...

为什么要做数据可视化

在当今信息爆炸的时代&#xff0c;数据已成为个人和企业最宝贵的资产之一。然而&#xff0c;仅仅拥有大量的数据并不足以支持明智的决策。数据可视化&#xff0c;作为一种将数据转化为图形形式的技术和方法&#xff0c;可以帮助我们更好地理解和分析数据&#xff0c;从而更准确…...

0基础学习VR全景平台篇 第108篇:全景图细节处理(下,航拍)

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; &#xff08;调色前图库&#xff09; &#xff08;原图-大图&#xff09; 一、导入文件 单击右下角导入按钮&#xff0c;选择航拍图片所在文件夹&#xff0c;选择图片&#xff0…...

linux查看文件内容命令more/less/cat/head/tail/grep

1.浏览全部内容more/less 文件&#xff1a; more&#xff1a;可以查看文件第一屏的内容&#xff0c;同时左下角有一个显示内容占全部文件内容的百分比&#xff0c;空格键会显示下一屏的内容&#xff0c;直到文件末尾 [rootmaster data]# more file1less&#xff1a;相较于mor…...

VBA窗体跟随活动单元格【简易版】

本篇博客与以往的风格不同&#xff0c;先上图再讲解。 这个效果是不是很酷&#xff0c;VBA窗体&#xff08;即UserForm&#xff0c;下文中简称为窗体&#xff09;可以实现很多功能&#xff0c;例如&#xff1a;用户输入数据&#xff0c;提供选项等等。如本博客标题标注&#…...

epiiAdmin框架注意事项

1&#xff0c;epiiAdmin文档地址&#xff1a; 简介/安装 EpiiAdmin中文文档 看云 2&#xff0c;项目性想新建模块 composer.json文件——autoload选项——psr-4下增加模块名称&#xff0c;然后执行composer update命令。 "autoload": {"psr-4": {"…...

数据仓库与ETL

什么是数据仓库 一种用于存储和管理数据的系统&#xff0c;提供一种统一方式&#xff0c;将不同来源、不同方式、不同时间的数据集成在一起。 数据仓库结构 主题域&#xff1a;一个特定领域的数据集&#xff0c;比如营销、销售、客户、库存等。 维度&#xff1a;定义数据的不…...

Centos7安装Gitlab--gitlab--ee版

1 安装必要依赖 2 配置GitLab软件源镜像 3 下载安装GitLab 4 查看管理员root用户默认密码 5 登录GitLab 6 修改密码 7 gitlab相关命令 1 安装必要依赖 sudo yum install -y curl policycoreutils-python openssh-server perl sudo systemctl enable sshd sudo systemctl sta…...

主题教育问题清单及整改措施2023年-主题教育对照六个方面个人剖析材料

无论前方路途多么坎坷&#xff0c;都要保持内心的坚定和勇敢。生活中没有什么不可战胜的困难&#xff0c;只有我们是否愿意去面对和克服。要相信自己的能力&#xff0c;相信自己拥有足够的智慧和力量去应对一切挑战 每一次的努力都不会白费&#xff0c;每一次的奋斗都是在为自己…...

php新手实战:自定义书源下载api

网上有很多第三方小说网站提供小说下载&#xff0c;而下载的过程无非就是搜索书籍&#xff0c;然后找到下载链接点击下载即可。只是类似这种“良心”的小说网站实在是太少。大多数仅支持在线阅读。而如今&#xff0c;我却要利用这种为数不多的“良心”小说站点提供的书源来作为…...

数据结构 - 5(二叉树7000字详解)

一&#xff1a;二叉树的基本概念 1.1树形结构 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 注意&am…...

xshell使用方法(超详细)

一、安装 下载最新版安装即可&#xff0c;不需要做任何配置。 安装完成后输入账号名和邮箱&#xff0c;确认后邮箱会收到一条确认邮件&#xff0c;将里面的链接点开即可免费使用&#xff08;仅安装后会出现&#xff0c;认证后以后再打开不需要重复操作&#xff0c;如果重新安…...

【数据库系统概论】第三章关系数据库标准语言SQL

选择题会考&#xff1a; 1.数据查询&#xff1a; SELECT&#xff1a;用于选择需要查询的列和行。 FROM&#xff1a;用于指定要查询的表。 WHERE&#xff1a;用于指定查询条件。 GROUP BY&#xff1a;用于按照指定的列对结果进行分组。 HAVING&#xff1a;用于指定分组条件…...

云计算是什么?学习云计算能做什么工作?

很多人经常会问云计算是什么&#xff1f;云计算能干什么&#xff1f;学习云计算能做什么工作&#xff1f;其实我们有很多人并不知道云计算是什么&#xff0c;小知今天来给大家讲讲学习云计算能做什么。 中国的云计算行业目前正处于快速发展阶段&#xff0c;随着互联网和数字化…...

ES6 -- 模块化(CommonJS、AMD、ES Module)

模块模式 将代码拆分成独立的块&#xff0c;然后再将这些块连接起来可以通过模块模式来实现。这种模式背后的思想很简单&#xff1a;把逻辑分块&#xff0c;各自封装&#xff0c;相互独立&#xff0c;每个块自行决定对外暴露什么&#xff0c;同时自行决定引入执行哪些外部代码…...

c# xml 参数读取读取的简单使用

完整使用之测试参数的读取&#xff08;xml&#xff09; 保存一个xml文档&#xff08;如果没有就会生成一个默认的 里面的参数用的是我们默认设置的&#xff09;&#xff0c;之后每次更改里面的某项&#xff0c;然后保存 类似于重新刷新一遍。 这里所用的xml测试参数前面需要加…...

gym原来是这样用的

今天down了一个深度强化学习的程序&#xff0c;但是试来试去总是跑不成功&#xff0c;第一句就出问题了 env gym.make("clusterEnv-v0").unwrapped总是报没有该环境&#xff0c;思想半天&#xff0c;然后发现这是自己写的环境&#xff0c;需要到gym中去注册才能使用…...

百度SEO优化技巧与布局(提升网站排名的5种有效方法)

网站SEO关键词介绍&#xff1a; SEO&#xff08;SearchEngineOptimization&#xff09;即搜索引擎优化&#xff0c;是通过一系列技术手段和策略&#xff0c;让网站在搜索引擎中获得更好的排名和流量。关键词是SEO优化的重要组成部分&#xff0c;通过关键词布局合理&#xff0c…...

文案配音软件哪个好?(适合新手使用)

随着短视频的逐渐普及&#xff0c;视频博主越来越多&#xff0c;所以很多朋友也期待成为视频博主。但是&#xff0c;如果你想成为一个有名的视频博主&#xff0c;你需要在很多层面上比别人做得更好。其中之一就是视频文字的配音。相信大部分人都没有配音的技巧&#xff0c;所以…...

excel映射xml方法

excel映射xml方法 创建xml模板 新建一个文本文件&#xff0c;编写模板并命名为xxx.xml <?xml version"1.0" encoding"UTF-8"?> <root><item ID""><surname></surname><man></man><woman>&…...

2023/10/15

文章目录 1.uniapp之Vue2升Vue3值得注意的几点1.1 页面生命周期的使用1.2 引入资源的方式 2. 浏览器本地存储之Cookie和webStorage3. CSS变量 var()的用法4. CSS之实现线性渐变背景5. 图片无法和文字对齐的正确解决方案6. 使用正则处理接口返回的富文本内的图片7. transition实…...

Linux系统中如何开启和配置OpenGauss数据库的远程连接

文章目录 前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 前言 openGauss是一款开源关系型数据库管理系统&#xff0c;采用木兰宽松许可证v2发行。openGauss内核深度融合…...

【Docker】Docker网络及容器间通信详解

目录 背景 默认网络 1、bridge 网络模式 2、host 网络模式 3、none 网络模式 4、container 网络模式 自定义网络 容器间网络通信 IP通信 Docker DNS server Joined容器 前言 本实验通过docker DNS server和joined 容器两种方法实现Docker容器间的通信。Docker容器间…...

TikTok国际版 使用特网科技Bluestacks模拟器安装方法

特网科技Bluestacks模拟器主机 桌面自带Bluestacks模拟器 TikTok国际版Bluestacks模拟器搜索tiktot 登录google应用商店-安装TikTok 安装过程可能需要3-5分钟不等-配置过低可能会导致安装失败&#xff0c;建议升级更高内存。 安装完成-打开 安装成功APP-我的游戏查看 打开国际版…...

【Hello Algorithm】暴力递归到动态规划(四)

动态规划的数组压缩技巧 - 机器人走格子问题 题目是leetcode62题目原题 表示如下 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中…...

arm day 8

arm 写一段按键中断代码 main.c #include "uart.h" #include "key_it.h" int main() {char c;char *s;uart4_init();//串口初始化//中断初始化key_it_config();while(1){//保证主程序不结束}return 0; } src/key_it.c #include"key_it.h"voi…...

k8s-14 存储之volumes

Volumes配置管理 容器中的文件在磁盘上是临时存放的&#xff0c;这给容器中运行的特殊应用程序带来一些问题。首先&#xff0c;当容器崩溃时&#xff0c;kubelet 将重新启动容器&#xff0c;容器中的文件将会丢失因为容器会以干净的状态重建。其次&#xff0c;当在一个 Pod 中…...

二分图博弈

一张二分图&#xff0c;Alice和Bob每人走一步&#xff0c;不能重复走&#xff0c;谁不能走谁输 结论&#xff1a;若存在最大匹配不包含初始点&#xff0c;则Bob赢&#xff0c;否则Alice赢 以上图为例&#xff0c;红色为最大匹配。 首先对于Alice第一步只能走黑边。而Alice无论…...

【C++】C++11—— 包装器

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C学习 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C】C11…...

LED显示屏高刷新率和低刷新率有什么区别

LED显示屏的刷新率是指图像在LED显示屏上更新的速度&#xff0c;也即屏幕上的图像每秒钟出现的次数&#xff0c;它的单位是赫兹&#xff08;Hz&#xff09;。LED显示屏的刷新率越高&#xff0c;图像闪烁感就越小&#xff0c;稳定性也就越高&#xff0c;换言之对视力的保护也越好…...

有没有专门做翻译的网站/最近的重要新闻

原文地址&#xff1a;http://jason61719.blog.163.com/blog/static/11417604120106325114274/ 一、Eclipse,MyEclipse安装插件方法大全(dropins) 使用eclipse&#xff0c;最看重的还是它的插件数量比较多&#xff0c;使用起来比较方便&#xff0c;但是大多数人对eclipse的插件…...

做文化建设的网站/南宁百度快速优化

对于给定的大量APP&#xff0c;如何爬取与之对应的&#xff08;应用市场&#xff09;分类、描述的信息&#xff1f;且看下面分解。 1. 页面分析 当我们在豌豆荚首页搜索框输入微信后&#xff0c;会跳转到搜索结果的页面&#xff0c;其url为http://www.wandoujia.com/search?ke…...

做网站的应该怎么发广告/网络推广赚钱项目

首先说明一下我的系统配置&#xff1a;ubuntu 12.04 gcc 4.6.3 有几天没有使用ubuntu了&#xff0c;今天拿出来编程序&#xff0c;刚開始编译一个uboot1.1.6的代码。出现了stdio.h&#xff1a;没有那么个文件或文件夹的错误。由于我是用的arm-linux-gcc交叉编译编的&#x…...

公司网站制作方案/网站seo诊断报告

科技发展迅速&#xff0c;互联网行业不断壮大&#xff0c;随之软件产品层出不穷&#xff0c;如何保证产品质量&#xff0c;成为非常重要的事情&#xff0c;当下软件功能很复杂&#xff0c;测试工作量庞大&#xff0c;除了使用手工测试来验证功能以外&#xff0c;需要通过对大量…...

网站制作报价大约/阳泉seo

[转载博客](http://blog.csdn.net/pyfysf/article/details/72598518) 已经安装好了AndroidStudio&#xff0c;安装教程 本教程是作者自己摸索出来的&#xff0c;有不足之处还请大家海涵。多多拍砖&#xff0c;互相学习。 第一步&#xff1a;下载git&#xff0c;安装git客户端 …...

深圳西丽网站建设公司/百度的人工客服电话

特征 单个3 V电源操作&#xff08;2.7 V至3.6 V&#xff09; SNR70 dBc至65 MSPS时的奈奎斯特 SFDR85 dBc至65MSPS时奈奎斯特低功率&#xff1a; 300 mW至65 MSPS差分输入&#xff0c;带500 MHz带宽 片上参考和SHA DNL0.4 LSB 灵活模拟输入&#xff1a;1 V p-p至2 V p-p范围 偏…...