导购场景下的Groovy脚本引擎实战( 二 )


什么时候会触发的垃圾回收?
就算Class数量过多,只要触发GC,那应该就不会溢出了 。为什么上面会给出溢出的结论呢?这里引出下一个问题:
JVM回收Class对象的条件是什么?
针对上述问题,增加了对脚本语言的一个缓存的优化
private final TimedCache> groovyScriptClassCache = CacheUtil.newTimedCache(1000L * 60 * 60 * 24);private void compileScriptBinary(ScriptExecuteContext context, GroovyStandardScriptExecuteContext groovyContext) {Class scriptClass = groovyScriptClassCache.get(context.getScriptImplDTO().getScriptSource(), true, () -> {try (GroovyClassLoader classLoader = initializeGroovyClassLoader()) {return classLoader.parseClass(context.getScriptImplDTO().getScriptSource());}});Assert.that(Objects.nonNull(scriptClass), "ScriptClass不能为空");groovyContext.setScriptClass(scriptClass);}
4.安全问题
会自动引入java.util,java.lang包,方便用户调用,但同时也增加了系统的风险 。为了防止用户调用.exit或等方法导致系统宕机,以及自定义的片段代码执行死循环或调用资源超时等问题,提供了安全管理者 。
final SecureASTCustomizer groovyStandardSecureASTCustomizer;public GroovyClassLoader initializeGroovyClassLoader() {CompilerConfiguration compilerConfiguration = new CompilerConfiguration();//自定义CompilerConfiguration,设置groovy 编译选项,比如设置基类,设置默认导包,安全校验AST等等等,其他自定义操作compilerConfiguration.addCompilationCustomizers(groovyStandardSecureASTCustomizer);ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();return new GroovyClassLoader(contextClassLoader, compilerConfiguration);}
虽然可以通过控制允许的代码结构来保护源代码,但是对于脚本的编写仍然存在一定的安全风险,容易造成cpu暴涨、占用磁盘空间较大等影响系统运行的问题 。所以需要一些被动安全手段,比如采用线程池隔离,对脚本执行进行有效的实时监控、统计和封装等 。
5.项目与的集成 5.1引入依赖
org.codehaus.GroovyGroovy3.0.9
5.2封装脚本框架所需参数
5.2.1脚本框架上下文信息
/*** 脚本框架上下文*/public class ScriptExecuteContext {/*** 脚本定义code*/private String scriptCode;/*** 脚本版本号*/private Integer version;/*** 脚本定义*/private ScriptDTO scriptDTO;/*** 脚本实现*/private ScriptImplDTO scriptImplDTO;/*** 脚本扩展定义*/private ScriptFeatureDTO scriptFeatureDTO;/*** 脚本扩展实现*/private ScriptImplFeatureDTO scriptImplFeatureDTO;/*** 脚本预约执行器*/private ScriptFramework scriptFramework;/*** 脚本执行参数*/private ScriptExecuteParam scriptExecuteParam;/*** 脚本执行结果*/private ScriptExecuteResult scriptExecuteResult;}

导购场景下的Groovy脚本引擎实战

文章插图
5.2.脚本的上下文信息
/*** Groovy脚本上下文*/public class GroovyStandardScriptExecuteContext {/*** 脚本名称*/private String scriptClassName;/*** 脚本源码*/private String scriptClassSource;/*** 脚本依赖的参数 log 参数*/private GroovyStandardScriptSandBoxContext GroovyStandardScriptSandBoxContext;/*** 脚本依赖的参数 log*/private Map scriptFrameworkParam;/*** 依赖的feign*/private Map scriptFeignDependencyParam;/*** 依赖的参数 service*/private Map scriptDependencyParam;/*** 脚本参数*/private Map scriptParam;/*** 系统参数*/private Map systemParam;/*** 作用域的参数和变量*/private Binding scriptBinding;/*** 脚本转化的类信息*/private Class