文章目录
1、整合热身
1.1、适当的整合
- 并不所有应用都适合整合groovy
1.2、设置依赖
- 依赖groovy的lib
2、使用GroovyShell解析表达式和脚本
- 有点类似EL 表达式
2.1、开始简单
-
package com.jack.groovy.ch16 /** * @author liangchen* @date 2020/12/6 */ @Grab(group='org.apache.httpcomponents', module='httpcore', version='4.2.1') def shell = new GroovyShell() def result = shell.evaluate("12 + 23") assert result == 35 // 显示创建GroovyShell 一些case assert "Hello" == Eval.me("'Hello'") // 前面是值,后面是表达式 assert 1 == Eval.x(1, "x") // 两个数据相加 assert 3 == Eval.xy(1, 2, "x+y") // 三个数据相加 assert 6 == Eval.xyz(1, 2, 3, "x+y+z")
2.2、通过绑定传参
-
package com.jack.groovy.ch16 /** * @author liangchen* @date 2020/12/6 */ def binding = new Binding() binding.mass = 22.3 binding.velocity = 10.6 def shell = new GroovyShell(binding) // velocity ** 2 velocity的平方 22.3 * 10.6*10.6 / 2 def expression = "mass * velocity ** 2/2" assert shell.evaluate(expression) == 1252.814 binding.setVariable("mass", 25.4) assert shell.evaluate(expression) == 1426.972 // 绑定字段的值 def bindingFlow = new Binding(x: 6, y: 4) def shellFlow = new GroovyShell(bindingFlow) shellFlow.evaluate(''' xSquare = x * x yCube = y * y * y ''') assert bindingFlow.getVariable("xSquare") == 36 assert bindingFlow.yCube == 64 // 可以在 表达式完成赋值 def bindingLocal = new Binding() def shellLocal = new GroovyShell(bindingLocal) shellLocal.evaluate(''' def localVariable = 'local variable' bindingVariable = 'binding variable' ''') assert bindingLocal.getVariable("bindingVariable") == "binding variable"
2.3、在运行时生成动态类
-
package com.jack.groovy.ch16 /** * @author liangchen* @date 2020/12/6 */ // 利用 evalue 定义动态类 def shell = new GroovyShell() def clazz = shell.evaluate(''' class MyClass{ def method(){"value"} } return MyClass ''') assert clazz.name == "MyClass" def instance = clazz.newInstance() assert instance.method() == "value"
2.4、解析脚本
-
package com.jack.groovy.ch16 /** * @author liangchen* @date 2020/12/6 */ // 计算贷款利率 def monthly = "amount * (rate/12) / (1-(1+rate/12)**-numberOfMonths)" def shell = new GroovyShell() def script = shell.parse(monthly) script.binding.amount = 154000 script.rate = 3.75/100 script.numberOfMonths = 240 assert script.run() == 913.0480050387338 // 不需要重新解析 monthly 表达式 script.binding = new Binding(amount: 185000, rate: 3.50 / 100, numberOfMonths: 300) assert script.run() == 926.1536089487843
2.5、运行脚本和类
2.6、GroovyShell更深的参数
-
package com.jack.groovy.ch16 import org.codehaus.groovy.control.CompilerConfiguration /** * @author liangchen* @date 2020/12/6 */ // 通过配置CompilerConfiguration 类 // 继承 Script 抽象类,然后定义抽象方法 abstract class BaseScript extends Script{ def multiply(a, b) { a * b} } // 设置compiler配置, evaluate就可以实现这个抽象方法了 def conf = new CompilerConfiguration() conf.setScriptBaseClass("com.jack.groovy.ch16.BaseScript") def shell = new GroovyShell(conf) def value = shell.evaluate(''' multiply(5,6) ''') assert value == 30
3、使用groovy脚本引擎
3.1、设置引擎
-
// 创建engine def engine = new GroovyScriptEngine(".") //数组 def engine = new GroovyScriptEngine([".", "../folder"]) // url格式 def engine = new GroovyScriptEngine(["file://.", "http://someUrl"]*.toURL() as URL[])
3.2、运行脚本
3.3、定义不同资源连接器
4、使用GroovyClassLoader
4.1、解析和加载groovy 类
-
当前文件夹有个类(Hello.groovy)
-
class Hello { def greeting() { "Hello!" } }
-
使用GroovyClassLoader
-
def gc1 = new GroovyClassLoader() // 解析这个类 Class greetingClass = gc1.parseClass(new File("Hello.groovy")) assert "Hello!" == greetingClass.newInstance().greeting() // Java 调用方法 GroovyClassLoader gcl = new GroovyClassLoader(); Class greetingClass = gcl.parseClass(new File(" Hello.groovy ")); GroovyObject hello = (GroovyObject) greetingClass.newInstance(); Object[] args = {}; assert "Hello!".equals(hello. invokeMethod ("greeting", args));
-
4.2、鸡和蛋依赖问题
- grooy和java代码同时存在时候的问题
4.3、提供自定义资源加载器
- 需要继承GroovyResourceLoader,实现loadGroovySource方法
4.4、在安全盒子运行安全
-
grant codeBase "file:${server.home}/classes/~"{ permission java.security.AllPermission; }; grant codeBase "file:/restricted "{ permission java.util.PropertyPermission "file.encoding", "read" }
5、spring 整合
5.1、写groovy Bean
5.2、刷新bean
5.3、内嵌脚本
6、Riding Mustang 和JSR-223
6.1、介绍JSR-223
- Scripting for the java Platform (java脚本平台)
6.2、脚本引擎管理
-
脚本引擎API是 javax.script.ScriptEngineManager
-
import javax.script.ScriptEngine import javax.script.ScriptEngineManager /** * @author liangchen* @date 2020/12/12 */ ScriptEngineManager scriptEngineManager = new ScriptEngineManager() ScriptEngine engins = scriptEngineManager.getEngineByName("groovy") result = engins.eval("3+3") println result
6.3、编译和调用脚本引擎
-
package com.jack.groovy.ch16 import javax.script.Compilable import javax.script.CompiledScript import javax.script.Invocable import javax.script.ScriptEngine import javax.script.ScriptEngineManager /** * @author liangchen* @date 2020/12/12 */ ScriptEngineManager manager = new ScriptEngineManager() ScriptEngine scriptEngine = manager.getEngineByName("groovy") Compilable compilable = (Compilable) scriptEngine //设置一个值 compilable.put("name", "Dierk") //设置返回方法, 有点SQL预编译的味道 CompiledScript script = compilable.compile("return name") String dierksName = script.eval() println dierksName compilable.put("name", "Guillaume") String guillaumesName = script.eval() println guillaumesName // Invoke 调用方法 ScriptEngineManager managerInvoke = new ScriptEngineManager() ScriptEngine engine = managerInvoke.getEngineByName("groovy") Invocable invocable = (Invocable) engine // 添加一个方法 invocable.eval("def upper(s) {s.toUpperCase()}") // 调用方法(变成大写) Object s = invocable.invokeFunction("upper", "Groovy") // 添加一个加法的方法 invocable.eval("def add(a,b){a+b}") invocable.invokeFunction("add", new Integer(1), new Integer(2)) // 调用String 的方法endsWith assertTrue(invocable.invokeMethod(s, "endsWith", "Y"))
6.4、多态编程
-
import javax.script.ScriptEngineManager /** * @author liangchen* @date 2020/12/12 */ // 多态编程 ,定义一个斐波那契数列 def mgr = new ScriptEngineManager() assert mgr.getEngineByName("javascript").eval(''' function factorial(n){ if(n == 0) {return 1;} return n * factorial(n-1); } factorial(4) ''') == 24.0
7、精通编译配置
-
自定义加载配置类
-
import org.codehaus.groovy.control.CompilerConfiguration import org.codehaus.groovy.control.customizers.ImportCustomizer /** * @author liangchen* @date 2020/12/12 */ def conf = new CompilerConfiguration() conf.setScriptBaseClass("com.jack.groovy.ch16.BaseScript") def shell = new GroovyShell(conf) def value = shell.evaluate(''' multiply(5,6) ''') assert value == 30 // 导入自定义类 def config = new CompilerConfiguration() def customizer = new ImportCustomizer() customizer.addImports('java.util.concurrent.atomic.AtomicInteger', 'java.util.concurrent.atomic.AtomicLong') config.addCompilationCustomizers(customizer) def shells = new GroovyShell(config) def values = shells.evaluate(''' def myInt = new AtomicInteger(1) def myLong = new AtomicLong(2) ''')
7.1、导入自定义
7.2、资源上下文自定义
7.3、写你自己自定义
7.4、配置脚本的编译属性
8、选择整合机制
- 简单使用: Eval.me
- 单行输入: GroovyShell
- 多行,需要重加载: GroovyScriptEngine
- 解决依赖和安全问题: GroovyClassLoader
- 如果使用Spring: 使用groovy整合Spring
- 如果自由发挥: JSR-223规范整合