美文网首页Springboot
Java中引用动态脚本语言

Java中引用动态脚本语言

作者: AlienPaul | 来源:发表于2018-11-10 10:45 被阅读57次

在项目中有时候我们需要将部分需要经常修改的业务逻辑做成配置化。大家会首先想到各种形式的配置文件。然而,当业务逻辑真的无规律可循之时,我们如何组织配置文件呢?

也许大家会想,如果能在配置文件中编写动态的代码那该多好。这就引出了本片博文的内容,在Java中引入动态脚本,并获取动态脚本的执行结果。

使用Groovy Script动态脚本

Groovy Script以简单,语法贴近原生Java和执行速度快被大家广泛使用。下面讲解下在如何调用Groovy Script。

  1. 首先引入Groovy的依赖包
<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy</artifactId>
    <version>2.5.3</version>
</dependency>
  1. 编写如下Java代码。该示例为最简化的groovy script应用
// 创建Groovy Shell
GroovyShell groovyShell = new GroovyShell();

// 解析动态groovy script。这里的例子为获取a的length。脚本以string形式传入
Script script = groovyShell.parse("a.length()");

// 创建运行环境上下文的变量绑定
Binding binding = new Binding();
// 上下文放入a变量,值为"Hello"
binding.setProperty("a", "Hello");

// 设置绑定
script.setBinding(binding);

// 执行脚本,获取脚本执行结果
Object run = script.run();

// 打印出执行结果,输出为 5
System.out.println(run);

通过这个例子大家不难发现动态脚本的强大。只需要将脚本作为string,读入我们的Java代码当中就可以动态执行了。

使用JavaScript动态脚本

如果大家在项目中使用的是Java 8,建议大家使用JavaScript作为动态脚本。Java 8自带的Nashorn具有很好的性能,使用时也无需引用额外的jar包。

最简单的例子

让nashorn运行起来只需要如下2行代码:

// 获取nashorn脚本执行引擎
ScriptEngine nashorn = new ScriptEngineManager().getEngineByName("nashorn");
// 执行脚本, 控制台会打印出 Hello World
nashorn.eval("print('Hello World')");

使用上下文变量

上面例子也太简单了。如果想使用之前groovy script中的例子,指定上下文变量呢?

ScriptEngine nashorn = new ScriptEngineManager().getEngineByName("nashorn");

// 同理使用bindings设置上下文变量
Bindings bindings = new SimpleBindings();
bindings.put("a", "Hello");
nashorn.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
Object eval = nashorn.eval("a.length");
System.out.println(eval);

这段代码中setBindings方法中出现了ScriptContext.ENGINE_SCOPE。它的含义在以下代码中得到解释:

/**
     * ...
     * @param scope The specified scope.  Either <code>ScriptContext.ENGINE_SCOPE</code>,
     * <code>ScriptContext.GLOBAL_SCOPE</code>, or any other valid value of scope.
     * ...
*/
public void setBindings(Bindings bindings, int scope);

scope 参数值有两个:ScriptContext.ENGINE_SCOPEScriptContext.GLOBAL_SCOPE。接下来我们查看ScriptContext源代码:

   /**
     * EngineScope attributes are visible during the lifetime of a single
     * <code>ScriptEngine</code> and a set of attributes is maintained for each
     * engine.
     */
    public static final int ENGINE_SCOPE = 100;

    /**
     * GlobalScope attributes are visible to all engines created by same ScriptEngineFactory.
     */
    public static final int GLOBAL_SCOPE = 200;

这下他们的含义就一目了然了。ENGINE_SCOPE只对当前这个ScriptEngine有效,而GLOBAL_SCOPE对同一个ScriptEngineFactory创建出来的所有engine都生效。

读取外部JavaScript文件

如果JavaScript代码太长了不便于写在程序中怎么办?脚本引擎的eval方法支持从文件系统读取外部js文件。代码如下所示:

ScriptEngine nashorn = new ScriptEngineManager().getEngineByName("nashorn");

nashorn.eval(new FileReader("test.js"));

调用JavaScript方法

Nashorn 引擎还支持调用JavaScript中的特定函数。在Java中指定函数名和参数列表,函数执行结果再返回到Java中。

test.js

function fun1() {
    return "Hello from fun1";
}
ScriptEngine nashorn = new ScriptEngineManager().getEngineByName("nashorn");

// 读取test.js文件
nashorn.eval(new FileReader("test.js"));

// 转换nashorn为Invocable
Invocable invocable = (Invocable) nashorn;

// 显式指明调用fun1,参数列表为空数组
Object returnedValue = invocable.invokeFunction("fun1", new Object[]{});
// 打印调用结果,为 Hello from fun1
System.out.println(returnedValue);

更多资料

其他资料大家可以参考:

https://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html
https://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/

本博客为作者原创,欢迎大家参与讨论和批评指正。如需转载请注明出处。

相关文章

  • Java中引用动态脚本语言

    在项目中有时候我们需要将部分需要经常修改的业务逻辑做成配置化。大家会首先想到各种形式的配置文件。然而,当业务逻辑真...

  • 动态语言

    Java SE 6 新特性-对脚本语言的支持 动态调用动态语言,第 1 部分-引入 Java 脚本 API 动态调...

  • Groovy

    Groovy 是基于jvm的动态语言, 面向对象, 也可以是脚本语言。 与java比较 完全兼容java语法; 行...

  • 反射&动态代理

    反射 Java 的动态性体现在:反射机制、动态执行脚本语言、动态操作字节码 反射:在运行时加载、探知、使用编译时未...

  • JSP内置对象概述

    JSP使用java作为脚本语言、具有强大的对象处理能力、并且可以动态的创建Web页面的内容、但是java语言的对象...

  • 了不起的node.js学习笔记

    chapter 2 JavaScript概览 介绍 js是基于原型,面向对象, 弱类型的的动态脚本语言。 Java...

  • Weak Reference Soft Reference Ph

    JAVA 中的引用 JAVA 中存在4种引用,由强到弱依次是强引用、软引用、弱引用、虚引用。 强引用(Strong...

  • 面试题笔记

    Java中引用类型的区别,具体的使用场景 Java中引用类型分为四类:强引用、软引用、弱引用、虚引用。 强引用:强...

  • Java四种引用方式

    Java引用方式包括: 强引用、软引用、虚引用、弱引用 java的对象位于heap中,heap中的对象有强可及对象...

  • Java的引用

    参考链接: Java到底是值传递还是引用传递 Java的四种引用方式 Java中的强引用、软引用、弱引用和虚引用 ...

网友评论

    本文标题:Java中引用动态脚本语言

    本文链接:https://www.haomeiwen.com/subject/abtzxqtx.html