Java中使用Groovy的三种方式

来源:互联网 发布:晴天太阳能科技 知乎 编辑:程序博客网 时间:2024/05/02 22:58

一直想抽些时间回顾一下Groovy,非常感谢Groovy,虽然只使用了其很小一部分功能,却给项目运行带来了极大的便利。
该博客用于帮助那些需要在Java中集成Groovy的童鞋们。微笑


一.Groovy简单了解

 1.简介

    Groovy 是 用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同时又具有闭包和动态语言中的其他特性。
    Groovy是JVM的一个替代语言(替代是指可以用 Groovy 在Java平台上进行 Java 编程),使用方式基本与使用 Java代码的方式相同,该语言特别适合与Spring的动态语言支持一起使用,设计时充分考虑了Java集成,这使Groovy 与 Java 代码的互操作很容易。(注意:不是指Groovy替代java,而是指Groovy和java很好的结合编程。

    有人说,Groovy 是下一代的Java语言,不是说Groovy会替代Java,读者如果看过Java8 之 lambda表达式 与 Stream,不难发现lambda和Groovy中的闭包非常相似,Stream也融入了Groovy的思想,所以Java会越来越像Groovy。


 2.基本特性

  (1). 构建在强大的Java语言之上 并 添加了从Python,Ruby和Smalltalk等语言中学到的 诸多特征,例如动态类型转换、闭包和元编程(metaprogramming)支持。。
  (2).为Java开发者提供了 现代最流行的编程语言特性,而且学习成本很低(几乎为零)。
  (3). 支持DSL(Domain Specific Languages领域定义语言)和其它简洁的语法,让代码变得易于阅读和维护。
  (4).受检查类型异常(Checked Exception)也可以不用捕获。
  (5). Groovy拥有处理原生类型,面向对象以及一个Ant DSL,使得创建Shell Scripts变得非常简单。
  (6).在开发Web,GUI,数据库或控制台程序时 通过 减少框架性代码 大大提高了开发者的效率。
  (7).支持单元测试和模拟(对象),可以 简化测试。
  (8).无缝集成 所有已经存在的 Java对象和类库。
  (9).直接编译成Java字节码,这样可以在任何使用Java的地方 使用Groovy。
  (10).支持函数式编程,不需要main函数。
  (11).一些新的运算符。
  (12).默认导入常用的包。
  (13).断言不支持jvm的-ea参数进行开关。
  (14).支持对对象进行布尔求值。
  (15).类不支持default作用域,且默认作用域为public。
  (16).groovy中基本类型也是对象,可以直接调用对象的方法。


二.Java中使用Groovy的三种方式

 注:该Maven项目需要加入groovy-all包的依赖,这里使用的是最新的2.4.3版本。Eclipse中最好安装groovy的插件,便于调试。


 1.使用GroovyShell执行groovy脚本

  (1).通过evaluate方法执行groovy片段

    GroovyShell类提供一个evaluate方法,可直接运行一段字符串标示的groovy片段,如

// 调用evaluate方法直接执行一段Groovypublic static void testGroovy1() throws CompilationFailedException, IOException {GroovyShell groovyShell = new GroovyShell();groovyShell.evaluate("println 'My First Groovy shell.'");}
运行该方法输出如下:

My First Groovy shell.


    是不是很方便得意,GroovyShell的evaluate方法非常类似于Js的eva方法,可执行一段字符串。


  (2).通过evaluate方法调用groovy脚本文件

    首先新建一个Groovy文件:GroovyShell_1_1.groovy,里面有一个无参的方法sayHello,并在最后调用该方法。

// 不带参数的groovy方法def sayHello() {println 'Hello World.'// 如果不写return, groovy方法的默认最后一行为 方法的返回值//return "GroovyShell_1中的sayHello()方法的返回值""GroovyShell_1中的sayHello()方法的返回值"}// 运行groovy方法sayHello()

    在Java中就可以直接调用这个groovy文件执行了,方法如下:

// 调用GroovyShell_1_1public static void testGroovy2() throws CompilationFailedException, IOException {GroovyShell groovyShell = new GroovyShell();Object result = groovyShell.evaluate(new File("src/main/java/com/juxinli/groovy/GroovyShell_1_1.groovy"));logger.info(result.toString());}
运行结果如下:

Hello World.2015-06-10 18:23:27 [main] INFO tool.Tool_GroovyShell_1 : GroovyShell_1中的sayHello()方法的返回值

第一行是 方法sayHello输出的,第二行是sayHello方法的返回值


    当然,你可以传一个参数给Groovy文件并执行,新建GroovyShell_1_1.groovy,提供一个传参的sayHello方法,如:

// 带参数的groovy方法def sayHello(name) {println "Hello " + name + "."// 如果不写return, groovy方法的默认最后一行为 方法的返回值//return "GroovyShell_1中的sayHello()方法的返回值""GroovyShell_1中的sayHello(name)方法的返回值"}// 运行groovy方法sayHello(name)

    在Java中使用Groovy提供的Binding类来绑定参数

// 调用GroovyShell_1_2public static void testGroovy3() throws CompilationFailedException, IOException {// 调用带参数的groovy shell时,使用bind绑定数据Binding binding = new Binding();binding.setProperty("name", "Juxinli");GroovyShell groovyShell = new GroovyShell(binding);Object result = groovyShell.evaluate(new File("src/main/java/com/juxinli/groovy/GroovyShell_1_2.groovy"));logger.info(result.toString());}
运行结果如下:
Hello Juxinli.2015-06-10 18:30:01 [main] INFO tool.Tool_GroovyShell_1 : GroovyShell_1中的sayHello(name)方法的返回值

    是不是很简单得意,但evaluate方法提供的作用不止这些,查官方API你会发现


    evaluate方法还可以执行GroovyCodeSource(Groovy提供的包装类),或者 从互联网上执行一段脚本,还可以从输入流来执行相应的groovy等等。种类很多,大家有兴趣可以去研究。


 2.通过GroovyClassLoader动态加载Groovy Class

    我们比较熟悉Java的ClassLoader类加载器,当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。而GroovyClassLoader,顾名思义,就是用来加载Groovy类的加载器,想更深入了解,请参考Groovy深入探索——Groovy的ClassLoader体系。

    通过GroovyClassLoader执行Groovy的方法如下:

    首先新建了Groovy Class

package com.juxinli.groovyclass GroovyShell_2 {public String sayHello(String name, String sex, int age) {println 'GroovyShell_2 的sayHello(String name, String sex, int age)方法';return "name: " + name + ", sex: " + sex + ", age: " + age;}}

    在Tool_GroovyShell_2中就可以加载该Groovy Class了

public class Tool_GroovyShell_2 {private static Logger logger = Logger.getLogger(Tool_GroovyShell_2.class);private static GroovyClassLoader groovyClassLoader = null;public static void initGroovyClassLoader() {CompilerConfiguration config = new CompilerConfiguration();config.setSourceEncoding("UTF-8");// 设置该GroovyClassLoader的父ClassLoader为当前线程的加载器(默认)groovyClassLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config);}/** * 通过GroovyClassLoader加载GroovyShell_2,并反射调用其sayHello(String name, String sex, int age)方法 *  */public static String invokeSayHello(String name, String sex, int age) {String result = "";File groovyFile = new File("src/main/java/com/juxinli/groovy/GroovyShell_2.groovy");if (!groovyFile.exists()) {return result;}try {// 获得GroovyShell_2加载后的classClass<?> groovyClass = groovyClassLoader.parseClass(groovyFile);// 获得GroovyShell_2的实例GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();// 反射调用sayHello方法得到返回值Object methodResult = groovyObject.invokeMethod("sayHello", new Object[] {name, sex, age});if (methodResult != null) {result = methodResult.toString();}} catch (Exception e) {logger.warn("加载groovy类失败", e);}return result;}public static void main(String[] args) throws Exception {initGroovyClassLoader();System.out.println(invokeSayHello("张三", "男", 25));}}

    其方式和Java中类的加载反射类似,这里不再熬述。需要注意的是,GroovyClassLoader与Java中的加载器一样,同一个类名的类只能加载一次,如果想再次加载,必须调用GroovyClassLoader的clearCache()方法移除所有已经加载的Groovy Class,详细文档见Groovy在线文档。

运行结果:

GroovyShell_2 的sayHello(String name, String sex, int age)方法name: 张三, sex: 男, age: 25

第一行为GroovyShell_2.groovy的sayHello(...)方法中内部的输出,第二行为其返回的字符串。

 

 3.使用GroovyScriptEngine脚本引擎加载Groovy脚本

GroovyScriptEngine从指定的位置(文件系统,URL,数据库等等)加载Groovy脚本,并且随着脚本变化可重新加载它们。和GroovyShell一样,GroovyScriptEngine也可以传进变量值返回脚本的计算结果。这样我们可以把一些可用的计算公式或计算条件写入Groovy脚本中来执行应用计算。当这些公式或计算条件变更时,我们可更方便地进行更改计算。

    从文件夹中加载Groovy脚本的例子如下:

    首先在com.juxinli.groovy.shell包中新建三个groovy script

package com.juxinli.groovy.shelldef sayHello(String name) {println "Hello, " + name"GroovyShell_3_1中的sayHello()方法的返回值"}sayHello(name)
GroovyShell_3_1.groovy


package com.juxinli.groovy.shelldef sayHello(String name) {println "你好, " + name"GroovyShell_3_2中的sayHello()方法的返回值"}sayHello(name)
GroovyShell_3_2.groovy


package com.juxinli.groovy.shelldef sayHello(String name) {println "Привет, " + name"GroovyShell_3_3中的sayHello()方法的返回值"}// 运行groovy方法sayHello(name)
GroovyShell_3_3.groovy

    使用GroovyScriptEngine从com.juxinli.groovy.shell包中加载、运行这些script

public class Tool_GroovyShell_3 {public static void main(String[] args) throws Exception {// GroovyScriptEngine的根路径,如果参数是字符串数组,说明有多个根路径GroovyScriptEngine engine = new GroovyScriptEngine("src/main/java/com/juxinli/groovy/shell/");//GroovyScriptEngine engine = new GroovyScriptEngine(new String[] {"src/main/java/com/juxinli/groovy/shell/"});Binding binding = new Binding();binding.setVariable("name", "juxinli");Object result1 = engine.run("GroovyShell_3_1.groovy", binding);System.out.println(result1);Object result2 = engine.run("GroovyShell_3_2.groovy", binding);System.out.println(result2);Object result3 = engine.run("GroovyShell_3_3.groovy", binding);System.out.println(result3);}}


运行结果:
Hello, juxinliGroovyShell_3_1中的sayHello()方法的返回值你好, juxinliGroovyShell_3_2中的sayHello()方法的返回值Привет, juxinliGroovyShell_3_3中的sayHello()方法的返回值

GroovyScriptEngine的构造的方法有很多,可以参考Groovy在线文档


    粗浅的回顾了一下,发现还有很多可以深入的地方,大家有好的 Groovy 应用 与发现,欢迎一起讨论、学习。可怜


附源码下载:

java_groovy项目


csdn下载地址

Java中使用Groovy的三种方式


GitHub下载地址

https://github.com/leonzm/java_groovy.git


参考&引用:

Groovy百度百科

Groovy入门教程
Groovy在线文档

groovy 三种运用

java中直接调用groovy的类

在Java里整合Groovy脚本的一个陷阱

Groovy深入探索——Groovy的ClassLoader体系

ClassLoader 详解及用途(写的不错)

Java中运行动态脚本 如Groovy


0 0
原创粉丝点击