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, ...
随机推荐
- mvn在线仓库搜索
使用Maven进行开发的时候,比较常见的一个问题就是如何寻找我要的依赖,比如说,我想要使用activeMQ,可是我不知道groupId,artifactId,和合适的version.怎么办呢?本文介绍 ...
- CentOS 6.9/Ubuntu 16.04搭建OpenVPN服务器以及客户端的使用
说明: 1.发现一个很奇怪的现象,CentOS和Ubuntu有着对用户不同的管理理念,比如CentOS中安装一切软件都是以root优先(su -),而Ubuntu则以当前用户优先,安装软件以sudo开 ...
- C# mvc 上传多个附件
<div class="col-xs-12 mcp-list-item" style="margin-top:20px"> <div clas ...
- 基于tiny4412的Linux内核移植(支持device tree)(三)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- IIS_未能映射路径“/”。
解决方法: 使用托管管道默认是为[经典]的应用程序池
- fmri 实验设计 / 范式设计/ paradigm design
reference:http://www.psychology.gatech.edu/cabi/Resources/Course/index.html sluggish 懒散的,无精打采的.哈哈,pp ...
- Unity3d设计模式之单例模式
单例模式我相信是所有设计模式之中运用最广泛的设计模式之一. 今天我们就来看看在unity中如何使用单例模式,在unity中,我们分两种单例,一种是继承monobehavior的单例,一种是普通单例. ...
- nano命令,vi ed pico sed joe emacs jed ex
nano命令 nano是一个字符终端的文本编辑器,有点像DOS下的editor程序.它比vi/vim要简单得多,比较适合Linux初学者使用.某些Linux发行版的默认编辑器就是nano. nan ...
- CFR Java Decompiler 反编译
java反编译,JAD & CFR 目前我们开发中大都使用JAD进行java反编译.这个工具已经过于陈旧,最突出的问题就是经常反编译出错. 使用CFR反编译工具能够很好的解决这个问题,并且支持 ...
- sql 改动表以及表字段
用SQL语句加入删除改动字段 1.添加字段 alter table docdsp add dspcode char(200) alter table tbl add meet ...