Groovy脚本引擎的执行本质只是接受context对象,然后基于context对象中的关键信息进行逻辑判断,输出结果。
参考文章:
文章1
文章2
文章3
文章4
在java中运行Groovy脚本,有三种比较常用的类支持:GroovyShell、GroovyClassLoader 以及 Java-Script引擎(JSR-223).
GroovyShell
GroovyShell允许在Java类中(甚至Groovy类)求任意Groovy表达式的值。您可使用Binding对象输入参数给表达式,并最终通过GroovyShell返回Groovy表达式的计算结果。
通常用来运行"script片段"或者一些零散的表达式(Expression)
GroovyClassLoader
用 Groovy 的 GroovyClassLoader ,它会动态地加载一个脚本并执行它。GroovyClassLoader是一个Groovy定制的类装载器,负责解析加载Java类中用到的Groovy类。
如果脚本是一个完整的文件,特别是有API类型的时候,比如有类似于JAVA的接口,面向对象设计时,通常使用GroovyClassLoader.
GroovyScriptEngine
GroovyShell多用于推求对立的脚本或表达式,如果换成相互关联的多个脚本,使用GroovyScriptEngine会更好些。GroovyScriptEngine从您指定的位置(文件系统,URL,数据库,等等)加载Groovy脚本,并且随着脚本变化而重新加载它们。如同GroovyShell一样,GroovyScriptEngine也允许您传入参数值,并能返回脚本的值。
首先导入Groovy包
注意:我的是这样导入包的,否则编译运行时会报异常:
参考解答:解决1 和 解决2
说白了就是springboot2.x版本和groovy2.5.x不能完全兼容。
该小节是在参考这篇文章后,加入一些自己的理解完成的。
在SpringBoot项目中,通过容器和依赖注入,可以很方便的实现开发功能。那么如何通过加载实例来动态编译脚本呢。
groovy支持通过GroovyShell预设对象,在groovy动态脚本中直接调用预设对象的方法。因此我们可以通过将spring的bean预设到GroovyShell运行环境中,在groovy动态脚本中直接调用spring容器中bean来调用其方法。
1、首先,自定义注解@GroovyFunction。用来标识用于绑定到GroovyShell的类。
2、service层用来编写自定义的方法,用@GroovyFunction注解标识该方法可以被绑定到GroovyShell中。
3、然后,利用SpringBoot中的Configuration类来设置Binding
首先配置类实现org.springframework.context.ApplicationContextAware接口,用来获取应用上下文。然后在配置从上下文获取到的指定Bean实例,并注入到groovy的Binding中。
这里,我是利用上文提到的@GroovyFunction注解来过滤需要的实例。
4、然后,定义一个请求类
这个其实没啥好说的,因为我不会再controller层请求两个参数。
5、最后,在controller层中,实现动态脚本运行
注意:下面是我的一些想法和实现
(1)采用单例模式,将GroovyShell在初始化时就实例化出来。以后每次都直接调用该实例。
(2)通过依赖注入,将已经绑定自定义方法的Binding实例注入进来
(3)维护一个HashTable,用于存放~~<expression,Script>~~ 的映射关系,这样就可以重复利用已经实例化过的Script的实例。
(4)多个请求同时操作HashTable,所以需要注意线程安全问题。
6、利用AOP记录请求日志信息
(1)自定义注解
(2)定义切面和切点
2020-03-26
突然发现代码会有问题(GC和线程安全问题)
详细内容参考: