最近设计一个数据统计系统,系统中上百种数据统计维度,而且这些数据统计的指标可能随时会调整.如果基于java编码的方式逐个实现数据统计的API设计,工作量大而且维护起来成本较高;最终确定为将"数据统计"的计算部分单独分离成脚本文件(javascript,或者Groovy),非常便捷了实现了"数据统计Task" 与 "数据统计规则(计算)"解耦,且可以动态的加载和运行的能力.顺便对JAVA嵌入运行Groovy脚本做个备忘.

Java中运行Groovy,有三种比较常用的类支持:GroovyShell,GroovyClassLoader以及Java-Script引擎(JSR-223).

1) GroovyShell: 通常用来运行"script片段"或者一些零散的表达式(Expression)

2) GroovyClassLoader: 如果脚本是一个完整的文件,特别是有API类型的时候,比如有类似于JAVA的接口,面向对象设计时,通常使用GroovyClassLoader.

3) ScriptEngine: JSR-223应该是推荐的一种使用策略.规范化,而且简便.

一.GroovyShell代码样例

1) 简单的表达式执行,方法调用

 /** * 简答脚本执行 * @throws Exception */
public static void evalScriptText() throws Exception{  //groovy.lang.Binding  Binding binding = new Binding();  GroovyShell shell = new GroovyShell(binding);  binding.setVariable("name", "zhangsan");  shell.evaluate("println 'Hello World! I am ' + name;");  //在script中,声明变量,不能使用def,否则scrope不一致.  shell.evaluate("date = new Date();");  Date date = (Date)binding.getVariable("date");  System.out.println("Date:" + date.getTime());  //以返回值的方式,获取script内部变量值,或者执行结果  //一个shell实例中,所有变量值,将会在此"session"中传递下去."date"可以在此后的script中获取  Long time = (Long)shell.evaluate("def time = date.getTime(); return time;");  System.out.println("Time:" + time);  binding.setVariable("list", new String[]{"A","B","C"});  //invoke method  String joinString = (String)shell.evaluate("def call(){return list.join(' - ')};call();");  System.out.println("Array join:" + joinString);  shell = null;  binding = null;
}

2)  伪main方法执行.

 /** * 当groovy脚本,为完整类结构时,可以通过执行main方法并传递参数的方式,启动脚本. */
public static void evalScriptAsMainMethod(){  String[] args = new String[]{"Zhangsan","10"};//main(String[] args)  Binding binding = new Binding(args);  GroovyShell shell = new GroovyShell(binding);  shell.evaluate("static void main(String[] args){ if(args.length != 2) return;println('Hello,I am ' + args[0] + ',age ' + args[1])}");  shell = null;  binding = null;
} 

3)  通过Shell运行具有类结构的Groovy脚本

 /** * 运行完整脚本 * @throws Exception */
public static void evalScriptTextFull() throws Exception{  StringBuffer buffer = new StringBuffer();  //define API  buffer.append("class User{")  .append("String name;Integer age;")  //.append("User(String name,Integer age){this.name = name;this.age = age};")  .append("String sayHello(){return 'Hello,I am ' + name + ',age ' + age;}}\n");  //Usage  buffer.append("def user = new User(name:'zhangsan',age:1);")  .append("user.sayHello();");  //groovy.lang.Binding  Binding binding = new Binding();  GroovyShell shell = new GroovyShell(binding);  String message = (String)shell.evaluate(buffer.toString());  System.out.println(message);  //重写main方法,默认执行  String mainMethod = "static void main(String[] args){def user = new User(name:'lisi',age:12);print(user.sayHello());}";  shell.evaluate(mainMethod);  shell = null;
}

4)  方法执行和分部调用

     /** * 以面向"过程"的方式运行脚本 * @throws Exception */  public static void evalScript() throws Exception{  Binding binding = new Binding();  GroovyShell shell = new GroovyShell(binding);  //直接方法调用  //shell.parse(new File(//))  Script script = shell.parse("def join(String[] list) {return list.join('--');}");  String joinString = (String)script.invokeMethod("join", new String[]{"A1","B2","C3"});  System.out.println(joinString);  脚本可以为任何格式,可以为main方法,也可以为普通方法  //1) def call(){...};call();  //2) call(){...};  script = shell.parse("static void main(String[] args){i = i * 2;}");  script.setProperty("i", new Integer(10));  script.run();//运行,  System.out.println(script.getProperty("i"));  //the same as  System.out.println(script.getBinding().getVariable("i"));  script = null;  shell = null;  }  

二. GroovyClassLoader代码示例

1) 解析groovy文件

     /** * from source file of *.groovy */  public static void parse() throws Exception{  GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader());  File sourceFile = new File("D:\\TestGroovy.groovy");  Class testGroovyClass = classLoader.parseClass(new GroovyCodeSource(sourceFile));  GroovyObject instance = (GroovyObject)testGroovyClass.newInstance();//proxy  Long time = (Long)instance.invokeMethod("getTime", new Date());  System.out.println(time);  Date date = (Date)instance.invokeMethod("getDate", time);  System.out.println(date.getTime());  //here  instance = null;  testGroovyClass = null;  }  

2) 如何加载已经编译的groovy文件(.class)

     public static void load() throws Exception {  GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader());  BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\TestGroovy.class"));  ByteArrayOutputStream bos = new ByteArrayOutputStream();  for(;;){  int i = bis.read();  if( i == -1){  break;  }  bos.write(i);  }  Class testGroovyClass = classLoader.defineClass(null, bos.toByteArray());  //instance of proxy-class  //if interface API is in the classpath,you can do such as:  //MyObject instance = (MyObject)testGroovyClass.newInstance()  GroovyObject instance = (GroovyObject)testGroovyClass.newInstance();  Long time = (Long)instance.invokeMethod("getTime", new Date());  System.out.println(time);  Date date = (Date)instance.invokeMethod("getDate", time);  System.out.println(date.getTime());  //here
    bis.close();  bos.close();  instance = null;  testGroovyClass = null;  }  

三. ScriptEngine

1) pom.xml依赖

 <dependency>  <groupId>org.codehaus.groovy</groupId>  <artifactId>groovy</artifactId>  <version>2.1.6</version>
</dependency>
<dependency>  <groupId>org.codehaus.groovy</groupId>  <artifactId>groovy-jsr223</artifactId>  <version>2.1.6</version>
</dependency> 

2) 代码样例

 public static void evalScript() throws Exception{  ScriptEngineManager factory = new ScriptEngineManager();  //每次生成一个engine实例  ScriptEngine engine = factory.getEngineByName("groovy");  System.out.println(engine.toString());  assert engine != null;  //javax.script.Bindings  Bindings binding = engine.createBindings();  binding.put("date", new Date());  //如果script文本来自文件,请首先获取文件内容  engine.eval("def getTime(){return date.getTime();}",binding);  engine.eval("def sayHello(name,age){return 'Hello,I am ' + name + ',age' + age;}");  Long time = (Long)((Invocable)engine).invokeFunction("getTime", null);  System.out.println(time);  String message = (String)((Invocable)engine).invokeFunction("sayHello", "zhangsan",new Integer(12));  System.out.println(message);
}

需要提醒的是,在groovy中,${expression} 将会被认为一个变量,如果需要输出"$"符号,需要转义为"\$".

关于ScriptEngine更多介绍,请参考.

JAVA嵌入运行Groovy脚本相关推荐

  1. Java内嵌Groovy脚本引擎进行业务规则剥离(一)

    2019独角兽企业重金招聘Python工程师标准>>> 一些常见商业应用程序或企业应用,大多都会遇上业务规则在一定的条件下,允许进行一些灵活的配置,以满足业务变化的需要. 解决的方式 ...

  2. java rhino 运行 js_java 脚本引擎Rhino执行js代码和文件

    测试js脚本引擎 public class helloworld { public static void main(String[] args) throws Exception { //获得脚本引 ...

  3. java groovy脚本_JAVA嵌入Groovy脚本

    Java中运行Groovy,有三种比较常用的类支持:GroovyShell,GroovyClassLoader以及Java-Script引擎(JSR-223). GroovyShell: 通常用来运行 ...

  4. java 嵌入groovy_嵌入Groovy

    原文链接  译者: 李璟(jlee381344197@gmail.com) (本站正在翻译groovy系列文章,有兴趣同学可以加入我们) Groovy就其本身而言,在不同的场景下都算是一门非常不错的编 ...

  5. 使用java运行Python脚本并获取返回值

    java运行Python脚本并获取返回值 java运行Python脚本并获取返回值 使用runtime类实现在java中运行Python脚本,话不多说,直接上代码 java运行Python脚本并获取返 ...

  6. 【Groovy】Groovy 脚本调用 ( Linux 中调用 Groovy 脚本 | Windows 中调用 Groovy 脚本 )

    文章目录 前言 一.Linux 中调用 Groovy 脚本 二.Windows 中调用 Groovy 脚本 前言 在 命令行 , Groovy 脚本 , Groovy 类 , Java 类中 , 可以 ...

  7. Groovy脚本基础全攻略

    1 背景 Groovy脚本基于Java且拓展了Java,所以从某种程度来说掌握Java是学习Groovy的前提,故本文适用于不熟悉Groovy却想快速得到Groovy核心基础干货的Java开发者(注意 ...

  8. java 调用groovy脚本,实现多个sql按指定逻辑运行,可做报表预聚合

    java 调用groovy脚本,实现多个sql按指定逻辑运行,可做报表预聚合 1.引入pom <dependency><groupId>org.codehaus.groovy& ...

  9. java groovy jar包_如何将jar包包含在groovy脚本中?

    如果你真的需要,你也可以在运行时加载一个JAR: this.getClass().classLoader.rootLoader.addURL(new File("file.jar" ...

最新文章

  1. iOS.Performance-trick-presentViewController-is-so-slow-in-didSelectRowAtIndexPath
  2. Android移动开发之【Android实战项目】Recyclerview添加花色分割线
  3. 站长就是个太监^_^
  4. java学习(129):hashmap的方法
  5. profiling定位nodejs程序消耗情况
  6. 访问者模式(Visitor)
  7. 谷歌浏览器一进百度空间就崩溃的临时解决方法
  8. 用jQuery实现.net 2.0 treeview客户端无刷新操作的实例
  9. 拼多多和酷家乐面试经历总结(已拿offer)
  10. pygame.mixer.music
  11. 二、 分式化简(LCP2)
  12. uniapp 日期时间 计算
  13. 人工智能轨道交通行业周刊-第44期(2023.5.8-5.14)
  14. RT-Thread 4.1.0 特性解析之LIBC与POSIX
  15. 信奥中的数学 组合篇 相关资料汇总(2022.07.08)
  16. 电脑误删除的文件怎么恢复
  17. day32_安卓基础之activity生命周期_receiver广播接收者
  18. 第一篇:基于小米手机的,解锁教程教学
  19. 开源流程引擎activiti、flowable、camunda选哪个好?
  20. 2020东京奥运会数据集echarts可视化分析

热门文章

  1. linux0.11 init函数,linux0.11启动与初始化
  2. linux 嵌入式 人工智能,嵌入式人工智能有哪些相关技术
  3. mysql服务remove失败_《MySQL数据库》MySql简介、下载与安装
  4. Vscode多个窗口显示多个选项卡/Tabs
  5. 20190906:(leetcode习题)Shuffle an Array
  6. 用php绘制空心圆,html5使用canvas画空心圆与实心圆_html5教程技巧
  7. java判断字符串是子串_【Java】判断字符串是否包含子字符串
  8. python 两个df求相同的行_python – Pandas df操作:如果其他列行重复,则返回值列表的新列...
  9. java ztree json_java 树形转换JSON 工具类 / 树形子父级菜单递归 JSON 格式
  10. div中赋值html字符串