Java动态调用groovy脚本代码教程
goovy简介
Goovy是一种基于Java虚拟机(JVM)的动态编程语言,它结合了Python、Ruby和Smalltalk的许多强大特性,并能够与Java完美结合,使用Java所有的库。以下是关于Goovy的详细解释:
语法
Goovy的语法非常简洁明了,类似于Python和Ruby。它支持动态类型和静态类型,可以在运行时进行类型检查和推断。Goovy还支持闭包、高阶函数和匿名函数等特性,这些特性使得代码更加简洁、易于阅读和维护。
类型系统
Goovy的类型系统非常灵活,支持动态类型和静态类型。在动态类型的情况下,变量的类型会在运行时自动推断。在静态类型的情况下,变量的类型需要在编译时声明。Goovy还支持类型转换和类型检查,使得代码更加健壮和可读。
闭包
Goovy支持闭包,闭包可以捕获其创建时所在的词法作用域中的变量。闭包可以作为参数传递给函数,也可以作为函数的返回值。闭包使得代码更加简洁、灵活和可重用。
高阶函数
Goovy支持高阶函数,高阶函数是指接受其他函数作为参数或返回函数的函数。高阶函数使得代码更加简洁、易于阅读和维护。
反射
Goovy支持反射,反射是指在运行时检查程序的行为和结构的能力。通过反射,可以在运行时获取类的信息、创建对象、调用方法等。反射使得代码更加灵活和可扩展。
并发编程
Goovy支持并发编程,它提供了类似于Java的线程和锁等机制,同时也提供了类似于Python的协程和异步编程等机制。这些机制使得开发人员可以更加轻松地编写并发程序,提高程序的性能和可靠性。
集成Java库
Goovy可以无缝集成Java库,开发人员可以使用Java所有的库来编写Goovy代码。这使得开发人员可以更加方便地利用现有的Java资源,同时也使得Goovy成为了一种非常灵活的动态脚本语言。
应用场景
Goovy适用于各种应用场景,例如Web开发、桌面应用、移动应用、游戏开发等。它既可以作为主要开发语言使用,也可以作为辅助语言使用,与Java完美结合,提高开发效率和代码质量。
总之,Goovy是一种非常强大的动态编程语言,它结合了Python、Ruby和Smalltalk的许多强大特性,并能够与Java完美结合,使用Java所有的库。Goovy的语法简洁明了、类型灵活、支持闭包和高阶函数等特性,使得代码更加简洁、易于阅读和维护。同时,Goovy还支持反射和并发编程等机制,使得程序更加灵活和可扩展。Goovy可以无缝集成Java库,使得开发人员可以更加方便地利用现有的Java资源。总之,Goovy是一种非常优秀的编程语言,适用于各种应用场景,值得广大开发人员学习和使用。
引入pom依赖
在maven项目中pom.xml添加如下依赖
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.11</version>
</dependency>
代码实现
创建一个名为ScriptProvider的groovy脚本辅助类,实现java调用groovy脚本中的方法。完整代码如下:
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import lombok.extern.slf4j.Slf4j;
import org.springblade.coalface.modules.opcua.dto.OpcData;
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 tarzan
*/
@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 float calStentHeight(int i, List<OpcData> dataValues){
Object[] objects = new Object[]{i,dataValues};
Object result=groovyObject.invokeMethod("calStentHeight",objects);
return Float.parseFloat(result.toString());
}
public float revisedStentHeight(int i, float value){
Object[] objects = new Object[]{i,value};
Object result=groovyObject.invokeMethod("revisedStentHeight",objects);
return Float.parseFloat(result.toString());
}
public float revisedStentStroke(float value) {
Object[] objects = new Object[]{value};
Object result=groovyObject.invokeMethod("revisedStentStroke",objects);
return Float.parseFloat(result.toString());
}
}
- app.work-face 是在spring配置文件中的goovy脚本名称
- etc/“+name+”.groovy 是指在项目根目录下 etc文件夹下 的某个 goovy脚本
groovy脚本代码示例
import org.springblade.coalface.modules.opcua.dto.OpcData
def calStentHeight(int i,List<OpcData> dataValues){
float d= dataValues.get(i).getValue()
def f1=0.175
def f2=0.136
def e= new BigDecimal(Float.toString(d)).add(f1).add(f2)
return e.doubleValue()
}
def revisedStentHeight(int i,float height){
int stentNo=i+1
if(stentNo<=2||stentNo>=92){
height=height>3.3||height<1.15?3.3:height
}else{
if(height>1.9){
height=1.9
}
if(height<1.15){
height=1.2
}
}
return height
}
def revisedStentStroke(float stroke){
if(stroke>900F){
stroke=900F
}
if(stroke<=0F){
stroke=0F
}
return stroke
}
- groovy 脚本中可以直接引入java的类,使用java对象的方法和属性
调用代码示例
@Resource
private ScriptProvider scriptProvider;
private void test() {
float revised = scriptProvider.revisedStentStroke(modification);
}
- 注入ScriptProvider工具类
- 通过ScriptProvider工具类调用对应grovvy脚本中的方法
动态监听脚本
当脚本被修改时候,java代码重新加载groovy脚本中的最新代码,需要一个监听工具类FileSystemWatcher,完整代码如下:
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
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;
@Async
public void modifyWatch(){
try {
watch(StandardWatchEventKinds.ENTRY_MODIFY);
} catch (IOException | InterruptedException e) {
log.error(e.getMessage());
}
}
@SuppressWarnings({"unchecked", "BusyWait"})
private void watch(WatchEvent.Kind<Path> eventKind) throws IOException, InterruptedException {
// 定义你想要监听的路径
Path path = Paths.get("etc");
// 创建 WatchService
WatchService 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);
}
}
// 重置 WatchKey,以便接收下一个事件
boolean valid = key.reset();
if (!valid) {
break;
}
//睡眠1秒
Thread.sleep(1000);
}
}
}
- @SuppressWarnings 用于抑制编译器产生某些警告,@SuppressWarnings({“unchecked”, “BusyWait”})告诉编译器不要对未检查的类型转换和忙等待产生警告。
- 这个监听工具类,需要在项目启动的时候调用它的监听方法。下面是代码示例:
创建一个启动监听类 AppStartedListener ,当项目启动完成后,就会调用,groovy脚本文件修改事件,当groovy脚本内的代码被修改后,保存groovy脚本时,会触发更新ScriptProvider类中加载的groovy脚本代码,实现动态更新。
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springblade.coalface.script.FileSystemWatcher;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
*
* @author tarzan
* @date 2023-10-05
*/
@Slf4j
@Component
public class AppStartedListener implements ApplicationListener<ApplicationStartedEvent> {
@Resource
private FileSystemWatcher fileSystemWatcher;
@SneakyThrows
@Override
public void onApplicationEvent(@NonNull ApplicationStartedEvent event) {
fileSystemWatcher.modifyWatch();
log.info("服务初始化。。。");
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!