Java动态从外部加载groovy脚本并执行。因为java可以直接把对象绑定到groovy脚本中执行,所以完全可以把一些系统中不确定的处理留下钩子,用groovy脚本处理,逻辑变了就直接改脚本,不用走发布流程。
核心代码
CompilerConfiguration conf = new CompilerConfiguration();conf.setDebug(false);shell = new GroovyShell(conf);String extCP = "/extlib/xxx.jar";shell.getClassLoader().addClasspath(extCP);String scriptName = "Script.groovy";String scriptText = "String hello(){ return args[0] }";Script script = (Class<Script>) shell.parse(scriptText, scriptName).getClass();Thread.currentThread().setContextClassLoader(shell.getClassLoader());//获取groovy代码中的hello方法Method method = script.getDeclaredMethod("hello");Script instance = script.newInstance();Map bindings = instance.getBinding().getVariables();bindings.clear();//绑定args全局变量bindings.put("args", args);String ret = method.invoke(instance);bindings.clear();
依赖
<dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-json</artifactId><version>2.5.4</version><scope>provided</scope></dependency><dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-sql</artifactId><version>2.5.4</version><scope>provided</scope></dependency><!-- groovy-all does not include groovy-dateutil by default, so must explicitlyinclude it here --><dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-dateutil</artifactId><version>2.5.4</version></dependency><dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-jsr223</artifactId><version>2.5.4</version></dependency>
优化
可以根据脚本内容/脚本id等对script / method 来进行缓存,避免每次执行都要编译。编译会有大量的时间消耗,并造成metaspace增长。
