Jvm上如何运行其他语言?JSR223规范最详细讲解
一
在Java的平台里,其实是可以执行其他的语言的。包括且不仅限于jvm发展出来的语言。
有的同学可能会说,在java项目里执行其他语言,这不吃饱了撑着么,java体系那么庞大,各种工具一应俱全,放着好好的java不写,还要去执行其他语言干嘛。
写java的都知道,java是需要事先编译的,这意味着你很难去在运行中改变编译好的class信息,除非你用字节码等技术栈,但是这也是需要很大的成本的。要想在运行中很方便的改变业务逻辑,其实用java去执行其他的脚本语言是一个好办法。况且有的脚本语言有着比java更简洁的语法特性。
有兴趣的小伙伴也可以看看之前的这篇文章:Java项目有可能做到所有的代码逻辑均可热部署吗?
二
在java中执行其他语言,可能你会觉得这应该很复杂,需要去学习每种语言包相关的api。
笔者是开源框架LiteFlow的作者,在规则引擎LiteFlow中实践并支持了许多的其他语言,如groovy,js,python,lua等。
我可以负责任的说,在Java平台中调用其他脚本语言,其实一点都不复杂,你无需关心每种语言的实际api。
这一切都归功于一个规范:JSR223
。
相信有大部分人没听过这个Java平台的规范。
JSR223规范最初在Java6平台被提出,提供了一套标准的API为脚本语言的执行提供了内置支持。
也就是说,你只要熟悉这一套API就能执行大部分的脚本语言。
而且这套API的使用也是非常方便的,几个核心方法仔细看个10分钟就能明白如何使用。
三
来个最简单的例子:
//获得javascript的脚本引擎
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
//进行脚本编译
String script = "function process(){\n" +
"var a=10\n" +
"var b=3\n" +
"return a*b-c\n" +
"}\n" +
"process()";
CompiledScript compiledScript = ((Compilable) scriptEngine).compile(script);
//绑定java的参数
Bindings bindings = new SimpleBindings();
bindings.put("c", 5);
//执行并打印结果
Object result = compiledScript.eval(bindings);
System.out.println(result);
上述代码演示的是用JSR223 API去执行javascript语言。值得一提的是,java内置了javascript引擎,你无需引入任何第三方包依赖就可以获得这个引擎。
整个过程分4块,分别是获得引擎,脚本编译,绑定java参数,执行。
在实际业务中,建议在系统启动的时候去编译脚本,然后把编译好的脚本对象compiledScript
对象给缓存起来,因为编译过程相对比较耗时,运行时每次去编译是个糟糕的设计。
如果在运行中改变了脚本,只需要重新去编译这个脚本并缓存其编译后的对象即可。
你只需要掌握以上代码,那几乎就已经掌握了JSR223规范的使用了。是不是很简单?
四
如果你想换成groovy脚本语言,那你需要依赖第三方依赖
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-jsr223</artifactId>
<version>3.0.8</version>
</dependency>
然后在上述的代码里获得引擎这块换成groovy即可:
...
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("groovy");
...
如果你想换成python,需要依赖第三方依赖
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.3</version>
</dependency>
然后在上述的代码里获得引擎这块换成python即可:
...
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("python");
...
看到这,是不是对利用JSR223
规范如何执行脚本恍然大悟了呢。
五
其实现在很多的语言在java平台都推出了自己的java三方执行依赖包,而且很多的包都支持了JSR223规范。只要支持了JSR223规范的语言,都可以利用上述的代码来执行。
JSR223规范的API可以支持java和其他语言的绑定和互通,一个java对象通过bindings对象也是可以传到脚本语言中的,在脚本语言中,你可以获得java的对象,来进行调用其方法和进行逻辑计算。
不过不同的语言调用操作符也许有所不同,比如groovy,javascript都是通过点操作符,和java很像,笔者在LiteFlow里新支持了Lua脚本,Lua脚本的对java对象的操作符是冒号。所以当你的项目支持相关的脚本语言之前,你先要熟悉下相关语言的语法。
六
用脚本语言来担当java平台中经常需要变动的部分是一个不错的选择。关键原因是脚本语言的编译,执行完全是动态的,这意味着你可以在java运行中改变脚本,重新编译,并执行。利用此特性来进行变相的热部署。
LiteFlow就是这样一款能够让你用多种脚本语言来定义你逻辑的规则引擎框架,这其中也利用了JSR223的规范API,不仅能用脚本来编写逻辑,还能进行规则编排。
项目官网:
gitee托管仓库:
希望大家都能从JSR223规范中找到一些设计你们相关业务系统的灵感。
Jvm上如何运行其他语言?JSR223规范最详细讲解的更多相关文章
- 前端模块化IIFE,commonjs,AMD,UMD,ES6 Module规范超详细讲解
目录 为什么前端需要模块化 什么是模块 是什么IIFE 举个栗子 模块化标准 Commonjs 特征 IIFE中的例子用commonjs实现 AMD和RequireJS 如何定义一个模块 如何在入口文 ...
- 为什么很多语言选择在JVM上实现
非常经济地实现跨平台.你的语言编译器后端只需要输出 JVM 字节码就可以.跨平台需要极大的工作量,举个例子,只是独立开发生成本地代码,就需要花费大量精力去针对不同平台和处理器进行优化(比如 Firef ...
- 牛逼了,教你用九种语言在JVM上输出HelloWorld
我们在<深入分析Java的编译原理>中提到过,为了让Java语言具有良好的跨平台能力,Java独具匠心的提供了一种可以在所有平台上都能使用的一种中间代码——字节码(ByteCode). 有 ...
- ZooKeeper服务器是用Java创建的,它在JVM上运行。
ZooKeeper服务器是用Java创建的,它在JVM上运行. 创建配置文件 使用命令 vi conf/zoo.cfg 和所有以下参数设置为起点,打开名为 conf/zoo.cfg 的配置文件. $ ...
- JVM 内存区域 (运行时数据区域)
JVM 内存区域 (运行时数据区域) 链接:https://www.jianshu.com/p/ec479baf4d06 运行时数据区域 Java 虚拟机在执行 Java 程序的过程中会把它所管理的内 ...
- 软件工程线上课程(C语言实践篇)学习心得总结
林牧 + 原创作品转载请注明出处 + <软件工程(C编码实践篇)>MOOC课程http://mooc.study.163.com/course/USTC-1000002006 软件工程的理 ...
- 转 PHP在JVM上的实现JPHP
前两天还在想,像Quercus只封装了PHP在Java上的Web接口,有没有实现了完整的JVM语言特性的东东,这不,来了. JPHP是一个面向Java虚拟机的PHP实现,支持PHP(5.3+)的很多特 ...
- Java语言编码规范(Java Code Conventions)
Java语言编码规范(Java Code Conventions) 名称 Java语言编码规范(Java Code Conventions) 译者 晨光(Morning) 简介 本文档讲述了Java语 ...
- 华为C语言编程规范
DKBA华为技术有限公司内部技术规范DKBA 2826-2011.5C语言编程规范2011年5月9日发布 2011年5月9日实施华为技术有限公司Huawei Technologies Co., Ltd ...
- JVM上的响应式流 — Reactor简介
强烈建议先阅读下JVM平台上的响应式流(Reactive Streams)规范,如果没读过的话. 官方文档:https://projectreactor.io/. 响应式编程 作为响应式编程方向上的第 ...
随机推荐
- SonarQube支持Gitlab授权登录
部署好SonarQube之后,由于我们内部使用的是自建的Gitlab仓库,即每个开发同学都有Gitlab账号,SonarQube我们就可以使用上Gitlab登录,这样就不需要再维护一套用户体系了. S ...
- Docker镜像仓库Harbor之Swagger REST API整合配置
转载自:https://cloud.tencent.com/developer/article/1010618 1.Swagger 介绍 Swagger 是一个规范和完整的框架,用于生成.描述.调用和 ...
- MySQL学习(4)---MySQL索引
ps:没有特殊说明,此随笔中默认采用innoDB存储引擎中的索引,且索引都是指B+树(多路平衡搜索树)结构组织的索引.其中聚集索引.复合索引.前缀索引.唯一索引默认都是使用B+树,统称为索引. 索引概 ...
- SQLServer配置开启TCP/IP连接
一 先启用SQLServer的TCP/IP协议 1.1 打开SQLServer配置管理器 1.2 启用TCP/IP 二 设置SQLServer端口 2.1 双击TCP/IP,弹出属性设置框 2.2 将 ...
- MySQL 窗口函数
1. 窗口函数概念和语法 窗口函数对一组查询行执行类似聚合的操作.然而,聚合操作将查询行分组到单个结果行,而窗口函数为每个查询行产生一个结果: 函数求值发生的行称为当前行 与发生函数求值的当前行相关的 ...
- Es 学习笔记 (1)
目录 前言 什么是es? es数据组织类比 应用场景 核心概念 集群 节点(node) 索引(Index) 文档类型(Type) 文档(Document) Mapping 核心简单域类型 分片(sha ...
- 13.MongoDB系列之分片简介
1. 分片概念 分片是指跨机器拆分数据的过程,有时也会用术语分区.MongoDB既可以手工分片,也支持自动分片 2. 理解集群组件 分片的目标之一是由多个分片组成的集群对应用程序来说就像是一台服务器. ...
- 多态特征,instanceof关键字和abstract类
多态 对象有多种状态.作用:提高程序的可扩展性. 一个对象具备多种状态的能力,这个程序是可扩展的. 前提: 必须有层级关系 继承 实现 继承:子类和父类的关系,一个父类可以有多个子类,说明父类的引用有 ...
- markdown第一天学习
Markdown学习 标题: 空格+标题名字后回车 二级标题 空格+标题名字后回车 三级标题 空格+标题名字后回车 四级标题 空格+标题名字后回车 字体 粗体 hello,world!------两边 ...
- 微服务 Zipkin 链路追踪原理(图文详解)
一个看起来很简单的应用,可能需要数十或数百个服务来支撑,一个请求就要多次服务调用. 当请求变慢.或者不能使用时,我们是不知道是哪个后台服务引起的. 这时,我们使用 Zipkin 就能解决这个问题. 由 ...