groovyshell java if_Java中使用Groovy的三种方式

一直想抽些时间回顾一下Groovy,非常感谢Groovy,虽然只使用了其很小一部分功能,却给项目运行带来了极大的便利。

该博客用于帮助那些需要在Java中集成Groovy的童鞋们。

smile.gif

一.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方法直接执行一段Groovy

public static void testGroovy1() throws CompilationFailedException, IOException {

GroovyShell groovyShell = new GroovyShell();

groovyShell.evaluate("println 'My First Groovy shell.'");

}运行该方法输出如下:

My First Groovy shell.

是不是很方便

proud.gif,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_1

public 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_2

public 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)方法的返回值

是不是很简单

proud.gif,但evaluate方法提供的作用不止这些,查官方API你会发现

483fc4abc3918a1cf89dd97793e8425f.png

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.groovy

class 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加载后的class

Class> 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.shell

def sayHello(String name) {

println "Hello, " + name

"GroovyShell_3_1中的sayHello()方法的返回值"

}

sayHello(name)GroovyShell_3_1.groovy

package com.juxinli.groovy.shell

def sayHello(String name) {

println "你好, " + name

"GroovyShell_3_2中的sayHello()方法的返回值"

}

sayHello(name)GroovyShell_3_2.groovy

package com.juxinli.groovy.shell

def 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, juxinli

GroovyShell_3_1中的sayHello()方法的返回值

你好, juxinli

GroovyShell_3_2中的sayHello()方法的返回值

Привет, juxinli

GroovyShell_3_3中的sayHello()方法的返回值

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

86a49e27d3966364498fb2aab4cc5d77.png

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

cute.gif

附源码下载:

java_groovy项目

csdn下载地址

Java中使用Groovy的三种方式

GitHub下载地址

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

参考&引用:

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2015-06-11 11:57

浏览 2302

评论

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值