Groovy小结:java调用Groovy方法并传递参数

@(JAVA总结)

1. 场景描述

在网上查了资料发现,java有三种方式调用groovy脚本。但是真正在实际的服务器环境中,嵌入groovy脚本往往需要满足下面的条件:

  1. 可以直接调用groovy脚本中的方法
  2. 能传递对象到groovy方法中,不仅仅是字符串
  3. 提供脚本缓存机制,不用每次调用脚本的时候,都到磁盘读取
  4. 修改groovy后能实时生效

只有满足了上面的这些要求,才能安心的将其嵌入到现有的Java后台服务中。

下面就来具体探讨下具体实现的步骤。

2. 解决方案

其实,GroovyScriptEngine类就已经提供了上面所说的功能。

主要使用GroovyScriptEngine.loadScriptByName来读取脚本,loadScriptByName方法内部提供了缓存功能,在读取groovy脚本的时候,会优先从缓存中读取,如果缓存中没有的话,才去读取脚本,如下:

2.1 相关测试类和脚本

在后面的测试后,会用到下面的java类和groovy脚本。

2.1.1 测试类Person.java

该类用于测试传递Java对象到Groovy脚本中

public class Person {
public String name;
public String address;
public Integer age; public Person(String name, String addr, Integer age){
this.name = name;
this.address = addr;
this.age = age;
} public String toString(){
return String.format("[Person: name:%s, address:%s, age:%s]", name,address, age);
}
}

2.1.2 测试脚本hello2.groovy

下面脚本中的两个方法用于测试方法的无参调用和带参调用

def helloWithoutParam(){
println "start to call helloWithoutParam!"
return "success, helloWithoutParam";
} def helloWithParam(person, id){
println "start to call helloWithParam, param{person:" + person + ", id:" + id + "}";
return "success, helloWithParam";
}

2.2 java调用Groovy脚本方法(无参)

public static void testGroovy2(){
try {
Class scriptClass = groovyScriptEngine.loadScriptByName("hello2.groovy");
GroovyObject scriptInstance = (GroovyObject)scriptClass.newInstance();
Object ret = scriptInstance.invokeMethod("helloWithoutParam", null);
System.out.println("testGroovy2:" + ret);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception e="+e.toString());
}
}

执行结果:

start to call helloWithoutParam!

testGroovy2: success, helloWithoutParam

2.3 java调用Groovy脚本方法(带参)

@SuppressWarnings({ "rawtypes" })
public static void testGroovy3(){
try {
Person person = new Person("wchi", "nanjing", 30);
Class scriptClass = groovyScriptEngine.loadScriptByName("hello2.groovy");
GroovyObject scriptInstance = (GroovyObject)scriptClass.newInstance();
Object ret = scriptInstance.invokeMethod("helloWithParam", new Object[]{person,"lxi"});
System.out.println("testGroovy3:" + ret);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception e="+e.toString());
}
}

返回结果:

start to call helloWithParam, param{person:[Person: name:wchi, address:nanjing, age:30], id:lxi}

testGroovy3: success, helloWithParam

2.4 封装的公用类

可以将上面的代码封装成公用类,这样就方便很多,如下:

public class GroovyCommonUtil {
private static final Logger log = LoggerFactory.getLogger(GroovyCommonUtil.class);
//该变量用于指明groovy脚本所在的父目录
static String root[]=new String[]{"bin/groovy/"};
static GroovyScriptEngine groovyScriptEngine; static{
try {
groovyScriptEngine=new GroovyScriptEngine(root);
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 用于调用指定Groovy脚本中的指定方法
* @param scriptName 脚本名称
* @param methodName 方法名称
* @param params 方法参数
* @return
*/
@SuppressWarnings({ "rawtypes"})
public Object invokeMethod(String scriptName, String methodName, Object... params) throws Exception{
Object ret = null;
Class scriptClass = null;
GroovyObject scriptInstance = null; try {
scriptClass = groovyScriptEngine.loadScriptByName(scriptName);
scriptInstance = (GroovyObject)scriptClass.newInstance();
} catch (ResourceException | ScriptException | InstantiationException | IllegalAccessException e1) {
log.warn("加载脚本["+scriptName+"]出现异常", e1);
throw new Exception("加载脚本"+scriptName+"失败");
} try {
ret = (String)scriptInstance.invokeMethod(methodName, params);
} catch (IllegalArgumentException e) {
log.warn("执行方法" + methodName + "参数出现异常, 参数为" + params, e);
throw new Exception("调用方法[" + methodName + "]失败,因参数不合法");
} catch(Exception e){
log.warn("执行方法" + methodName + "出现异常", e);
throw new Exception("调用方法[" + methodName + "]失败");
} return ret;
}

使用上面的公用类,改写的测试代码如下:

/**
* 测试没有参数的方法调用
*/
public static void testGroovyWithoutParam(){
String result = (String)GroovyCommonUtil.invokeMethod("hello2.groovy", "helloWithoutParam");
System.out.println("testGroovy4: " + result + "\n");
} /**
* 测试携带参数的方法调用
*/
public static void testGroovyWithParam(){
Person person = new Person("wchi", "nanjing", 30);
String result = (String)GroovyCommonUtil.invokeMethod("hello2.groovy", "helloWithParam", person, "testGroovy4");
System.out.println("testGroovy4: " + result + "\n");
}

Groovy小结:java调用Groovy方法并传递参数的更多相关文章

  1. 利用Ajax调用controller方法并传递参数

    一.背景由于近期工作需要将人脸识别功能与选课系统结合,但是对前端知识了解的很少,只能边做边学了,因此在这边把遇到的一些坑说明一下,希望能帮助到像我一样的初学者 二.具体内容这里采用框架为MVC,如果想 ...

  2. odoo14 button 事件调用python方法如何传递参数

    1 <field name="user_ids" 2 mode="kanban" 3 nolabel="1" 4 options=&q ...

  3. 工作随笔——Java调用Groovy类的方法、传递参数和获取返回值

    接触Groovy也快一年了,一直在尝试怎么将Groovy引用到日常工作中来.最近在做一个功能的时候,花了点时间重新看了下Java怎么调用Groovy的方法.传递参数和获取返回值. 示例Groovy代码 ...

  4. Java调用WebService方法总结(9,end)--Http方式调用WebService

    Http方式调用WebService,直接发送soap消息到服务端,然后自己解析服务端返回的结果,这种方式比较简单粗暴,也很好用:soap消息可以通过SoapUI来生成,也很方便.文中所使用到的软件版 ...

  5. Java调用WebService方法总结(5)--Axis2调用WebService

    Axis2是新一点Axis,基于新的体系结构进行了全新编写,有更强的灵活性并可扩展到新的体系结构.文中demo所使用到的软件版本:Java 1.8.0_191.Axis2 1.7.9. 1.准备 参考 ...

  6. java调用本地方法的时候报错 could not find the main class:xx.program will exit

    如图所示,当在java调用本地方法的时候报错 我的解决办法是把dll文件放到System.out.println(System.getProperty("java.library.path& ...

  7. Java调用IDL方法总结

    Java调用IDL方法总结 Java调用IDL程序,需要先在java中加载IDL的java包(javaidlb.jar),该包不需要下载,在IDL的安装目录中可以直接找到(C:\Program Fil ...

  8. cocos2d 中使用jni Java 调用 C++ 方法

    1.首先是LoadLibrary cocos2d中的C++代码会编译成一个.so文件.放在安卓文件夹下的libs/armeabi 下,然后java会load进来,这步我们不用做了,由于cocos2d已 ...

  9. Java 调用对象方法的执行过程

    弄清调用对象方法的执行过程十分重要.下面是调用过程的详细描述: 1) 编译器查看对象的声明类型和方法名.假设调用x.f(param),且隐式参数x声明为C类的对象.需要注意的是:有可能存在多个名为f, ...

随机推荐

  1. Ubuntu 16.04修改MAC地址以及网络常用设置(IP/DNS/网关)

    1.先停止桌面版自带的NetworkManager,这东西很难用,且有些设置需要重启. sudo systemctl stop NetworkManager.service sudo systemct ...

  2. HMAC的JAVA实现和应用

    1.简介: HMACSHA1 是从SHA1 哈希函数构造的一种键控哈希算法,被用作 HMAC(基于哈希的消息验证代码). 此 HMAC 进程将密钥与消息数据混合,使用哈希函数对混合结果进行哈希计算,将 ...

  3. NServiceBus入门:发布事件(Introduction to NServiceBus: Publishing events)

    原文地址:https://docs.particular.net/tutorials/intro-to-nservicebus/4-publishing-events/ 侵删. 这个教程到目前为止,我 ...

  4. jstack_查看当前进程及所属线程执行情况

    C:\Program Files\Java\jdk1.7.0_45\bin\jstack.exe   1.任务管理器:进程选择PID   2.命令行执行        cd C:\Program Fi ...

  5. Android内存优化9 内存检测工具3 MAT比Menmery Monitor更强大

    在Android性能优化第(一)篇---基本概念中讲了JAVA的四大引用,讲了一下GCRoot,第二篇Memory Monitor检测内存泄露仅仅说了Menmery Monitor的使用,这篇博客谈一 ...

  6. [转]How to handle Failed Rows in a Data Flow

    本文转自:http://www.rad.pasfu.com/index.php?/archives/23-How-to-handle-Failed-Rows-in-a-Data-Flow.html s ...

  7. QT5.11下载与安装教程

    一.QT软件下载 Qt 5.9 之后的安装包与之前相比,不再区分 VS 版本和 MinGW 版本,而是全都整合到了一个安装包中.因此,与之前的安装包相比,体积也是大了不少,以前是 1G 多,现在是 2 ...

  8. 流畅的python第十七章使用期物处理并发

    从 Python 3.4 起,标准库中有两个名为 Future 的类:concurrent.futures.Future 和asyncio.Future.这两个类的作用相同:两个 Future 类的实 ...

  9. Oracle imp关于fromuser 和 touser的用法

    fromuser就是把当前的dmp文件中的某一个用户下的数据取出.touser就是把现在dmp文件中的数据导入到目标库的指定user下.具体命令这样.exp userid=system/manager ...

  10. [Python爬虫] 之十二:Selenium +phantomjs抓取中的url编码问题

    最近在抓取活动树网站 (http://www.huodongshu.com/html/find.html) 上数据时发现,在用搜索框输入中文后,点击搜索,phantomjs抓取数据怎么也抓取不到,但是 ...