Groovy小结:java调用Groovy方法并传递参数
Groovy小结:java调用Groovy方法并传递参数
@(JAVA总结)
1. 场景描述
在网上查了资料发现,java有三种方式调用groovy脚本。但是真正在实际的服务器环境中,嵌入groovy脚本往往需要满足下面的条件:
- 可以直接调用groovy脚本中的方法
- 能传递对象到groovy方法中,不仅仅是字符串
- 提供脚本缓存机制,不用每次调用脚本的时候,都到磁盘读取
- 修改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方法并传递参数的更多相关文章
- 利用Ajax调用controller方法并传递参数
一.背景由于近期工作需要将人脸识别功能与选课系统结合,但是对前端知识了解的很少,只能边做边学了,因此在这边把遇到的一些坑说明一下,希望能帮助到像我一样的初学者 二.具体内容这里采用框架为MVC,如果想 ...
- odoo14 button 事件调用python方法如何传递参数
1 <field name="user_ids" 2 mode="kanban" 3 nolabel="1" 4 options=&q ...
- 工作随笔——Java调用Groovy类的方法、传递参数和获取返回值
接触Groovy也快一年了,一直在尝试怎么将Groovy引用到日常工作中来.最近在做一个功能的时候,花了点时间重新看了下Java怎么调用Groovy的方法.传递参数和获取返回值. 示例Groovy代码 ...
- Java调用WebService方法总结(9,end)--Http方式调用WebService
Http方式调用WebService,直接发送soap消息到服务端,然后自己解析服务端返回的结果,这种方式比较简单粗暴,也很好用:soap消息可以通过SoapUI来生成,也很方便.文中所使用到的软件版 ...
- Java调用WebService方法总结(5)--Axis2调用WebService
Axis2是新一点Axis,基于新的体系结构进行了全新编写,有更强的灵活性并可扩展到新的体系结构.文中demo所使用到的软件版本:Java 1.8.0_191.Axis2 1.7.9. 1.准备 参考 ...
- java调用本地方法的时候报错 could not find the main class:xx.program will exit
如图所示,当在java调用本地方法的时候报错 我的解决办法是把dll文件放到System.out.println(System.getProperty("java.library.path& ...
- Java调用IDL方法总结
Java调用IDL方法总结 Java调用IDL程序,需要先在java中加载IDL的java包(javaidlb.jar),该包不需要下载,在IDL的安装目录中可以直接找到(C:\Program Fil ...
- cocos2d 中使用jni Java 调用 C++ 方法
1.首先是LoadLibrary cocos2d中的C++代码会编译成一个.so文件.放在安卓文件夹下的libs/armeabi 下,然后java会load进来,这步我们不用做了,由于cocos2d已 ...
- Java 调用对象方法的执行过程
弄清调用对象方法的执行过程十分重要.下面是调用过程的详细描述: 1) 编译器查看对象的声明类型和方法名.假设调用x.f(param),且隐式参数x声明为C类的对象.需要注意的是:有可能存在多个名为f, ...
随机推荐
- [转]Java五个最常用的集合类之间的区别和联系
Map<String, ?>只能是只读模式,不能增加,因为增加的时候不知道该写入什么类型的值:Map<String, Object>可以读和写,只要是所有Object类的子类都 ...
- hibernate处理视图问题(记录)
Mark,在使用hibernate处理视图的时候.因为视图没有主键,这个用Myeclipse自动生成的POJO类就有两个.一个类名.java,一个是类名Id.java,而映射文件只有一个.因此造成一个 ...
- 用asyncio的异步网络连接来获取sina、sohu和163的网站首页
代码如下: import asyncio async def wget(host): print('wget %s...' % host) connect = asyncio.open_connect ...
- PHP 自定义字符串中的变量名解析
PHP 自定义字符串中的变量名解析 这样一个需求:页面的 title 可以在后台自定义,自定义内容中可能包含变量,变量用 {$var} 表示, 其中 $var 为变量名 将 title 字段存入数 ...
- minishift安装
先下载安装包 https://github.com/minishift/minishift/releases mac上运行命令 minishift start --vm-driver=virtualb ...
- WebLogic 1036的镜像构建
WebLogic1035版本构建出来的镜像有问题,部署应用激活后返回的是后面pod的ip和端口号,在1036版本和12.1.3版本都无此问题. weblogic 1036的Dockerfile [ro ...
- 用phonegap和jquery-mobile写android应用
今天纪录的是学习用phonegap和jquery-moblie来写android的过程.环境搭建. 我的习惯是直接上官网看文档,看get-started guide之类的文档.然后在看参考手册.然后就 ...
- Nios II uCLinux/Linux启动分析
1. 说明 本文采用的Linux源码版本来自Altera公司FTP.不考虑zImage生成的Compress过程.因为zImage是内核binary文件经过gzip 压缩,并在头部添加解压缩代码实现的 ...
- Shell学习:if语句 if -z -n -f -eq -ne -lt
if 条件then Commandelse Commandfi 别忘了这个结尾 If语句忘了结尾fitest.sh: line 14: sy ...
- Oracle之数据库安全
密码破解,大部分其实是通过枚举的方式,列出可能的密码,然后逐个尝试,直到找到真正的密码,有时也叫暴力破解.接下来,我们将举几个密码破解的例子. n 密码破解例1--- OrakelCrackert ...