Java - JSR223规范解读_在JVM上实现多语言支持

文章目录

  • 1. 概述
  • 2. 核心目标
  • 3. 支持的脚本语言
  • 4. 主要接口
  • 5. 脚本引擎的使用
    • 执行JavaScript脚本
    • 执行groovy脚本
      • 1. Groovy简介
      • 2. Groovy脚本示例
      • 3. 如何在Java中集成 Groovy
      • 4. 集成注意事项
  • 6. 与Java集成
  • 7. 常见应用场景
  • 8. 优缺点
  • 9. 总结

在这里插入图片描述

1. 概述

JSR223(Java Specification Request 223),也称为 Scripting for the Java Platform,是一个Java平台的标准接口,旨在让Java应用程序能够灵活地集成和执行脚本语言。它定义了一种可以在Java应用中嵌入不同脚本语言的统一接口,允许Java程序调用、执行脚本,并且支持将Java对象传递到脚本语言中。


2. 核心目标

JSR223的目标是提供一种标准的API,以便Java应用能够:

  • 动态地执行脚本代码
  • 支持多个脚本语言
  • 将Java应用中的对象传递到脚本环境中

3. 支持的脚本语言

JSR223并没有指定哪些脚本语言必须支持,但它的设计理念是能够支持多种脚本语言。常见的支持脚本语言包括:

  • JavaScript (Nashorn / GraalVM)
  • Groovy
  • JRuby
  • Jython (Python)
  • Lua
  • BeanShell

不同的脚本语言通过JSR223接口进行集成,这些脚本引擎作为JSR223的实现进行交互。


4. 主要接口

JSR223定义了几个关键接口来实现Java与脚本语言的交互:

  • ScriptEngine: 这个接口代表了一个脚本引擎,允许Java代码与具体的脚本语言引擎进行交互。每个脚本引擎都实现了这个接口。
  • ScriptEngineFactory: 用于创建脚本引擎的工厂类。通过这个工厂类,Java程序可以获得可用的脚本引擎实例。
  • Bindings: 用于在Java和脚本之间传递变量和对象。Bindings允许在脚本执行期间使用Java对象。

常见的实现类:

  • Nashorn(从Java 8开始包含,用于执行JavaScript)
  • GraalVM(一个多语言执行环境,支持更多语言的集成)

5. 脚本引擎的使用

脚本引擎是JSR223的核心部分,接下来看几个例子

执行JavaScript脚本

样例一: 使用Nashorn引擎执行JavaScript代码的示例。

package com.artisan.jsr223;
import javax.script.*;public class JSR223Example {public static void main(String[] args) throws ScriptException {// 创建一个脚本引擎管理器ScriptEngineManager manager = new ScriptEngineManager();// 获取JavaScript引擎ScriptEngine engine = manager.getEngineByName("nashorn");// 执行JavaScript代码engine.eval("print('Hello, JSR223')");// 使用绑定传递变量Bindings bindings = engine.createBindings();bindings.put("name", "Artisan");engine.eval("print('Hello, ' + name);", bindings);}
}

在这个例子中,我们通过 ScriptEngineManager 获取Nashorn引擎,执行简单的JavaScript代码,使用 Bindings 传递变量。

在这里插入图片描述


样例二:

package com.artisan.jsr223;import javax.script.*;public class JSR223Example {public static void main(String[] args) throws Exception {// 获得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()";// 检查脚本引擎是否支持编译if (scriptEngine instanceof Compilable) {Compilable compilable = (Compilable) scriptEngine;CompiledScript compiledScript = compilable.compile(script);// 绑定Java的参数Bindings bindings = new SimpleBindings();bindings.put("c", 5);// 执行并打印结果Object result = compiledScript.eval(bindings);System.out.println(result);} else {System.out.println("当前脚本引擎不支持编译功能");}}
}

在这里插入图片描述


执行groovy脚本

1. Groovy简介

Groovy是一个基于Java平台的动态语言,它简洁、表达力强,并且与Java兼容性极高。Groovy可以作为Java的脚本引擎,直接在Java应用中使用。Groovy的语法简洁,支持面向对象、闭包、动态类型等特性,通常用于快速开发和扩展功能。

2. Groovy脚本示例

假设我们要编写一个简单的Groovy脚本,来计算一个人的年龄,并根据年龄判断是否符合某个年龄段(如成年)。

// 定义一个函数来计算年龄
def calculateAge(birthYear) {def currentYear = 2024return currentYear - birthYear
}// 定义一个函数来判断是否成年
def isAdult(age) {return age >= 18
}// 调用计算年龄和判断是否成年
def birthYear = 1990
def age = calculateAge(birthYear)println("Age: ${age}")
if (isAdult(age)) {println("You are an adult.")
} else {println("You are not an adult.")
}

解释:

  • def:用于定义变量或函数,Groovy是一种动态语言,变量和函数不需要显式声明类型。
  • calculateAge:该函数接受一个出生年份,返回计算后的年龄(2024年减去出生年份)。
  • isAdult:根据传入的年龄判断是否成年,成年为18岁及以上。
  • println:Groovy的内建方法,输出结果。

运行结果:

Age: 34
You are an adult.

3. 如何在Java中集成 Groovy

假设我们希望在Java代码中动态执行这个Groovy脚本,可以通过JSR223来实现。以下是如何在Java中嵌入并执行Groovy脚本的示例:


import javax.script.*;public class GroovyTest {public static void main(String[] args) throws ScriptException {// 创建一个脚本引擎管理器ScriptEngineManager manager = new ScriptEngineManager();// 获取Groovy引擎ScriptEngine engine = manager.getEngineByName("groovy");// 定义Groovy脚本String script ="def calculateAge(birthYear) { " +"    def currentYear = 2024; " +"    return currentYear - birthYear; " +"}\n" +  // 添加换行符"def isAdult(age) { " +"    return age >= 18; " +"}\n" +  // 添加换行符"def birthYear = 1990; " +"def age = calculateAge(birthYear); " +"println('Age: ' + age); " +"if (isAdult(age)) { " +"    println('You are an adult.'); " +"} else { " +"    println('You are not an adult.'); " +"} ";// 执行Groovy脚本engine.eval(script);}
}

步骤:

  1. 使用 ScriptEngineManager 获取Groovy引擎。
  2. 编写Groovy脚本并将其传递给引擎。
  3. 使用 eval() 方法执行脚本,并输出结果。

运行结果:

Age: 34
You are an adult.

4. 集成注意事项

  • Groovy的依赖:如果在Java项目中使用Groovy脚本,需要将Groovy的JAR包(例如 groovy-jsr223-x.y.z.jar)添加到项目的依赖中。

Maven依赖示例:

   <dependency><groupId>org.apache.groovy</groupId><artifactId>groovy-jsr223</artifactId><version>4.0.24</version></dependency>
  • 性能考虑:Groovy作为动态语言,性能可能不如纯Java代码,特别是在大规模或频繁执行的场景中,可能会引入一定的开销。

6. 与Java集成

  • 变量传递:JSR223允许将Java对象传递给脚本语言。通过 Bindings 接口,可以将Java对象存储在脚本的上下文中,脚本语言也能访问这些对象。

  • 动态执行:使用脚本语言可以动态地执行Java代码段,这对于快速开发和修改业务逻辑非常有效。例如,可以通过Java调用Groovy脚本来快速增加一些动态功能而无需重新编译整个应用。


7. 常见应用场景

JSR223可以广泛应用于多个领域:

  • 动态配置和脚本扩展:在Java应用中使用脚本来动态修改行为。例如,可以用Groovy编写自定义的配置文件解析器。
  • 自动化测试:集成脚本语言用于编写自动化测试脚本。
  • Web应用:在Web应用中,使用JSR223集成脚本语言来编写自定义插件或扩展功能。例如,支持JavaScript来扩展服务器端的业务逻辑。
  • 数据处理:在Java应用中使用脚本来处理数据或执行算法。

8. 优缺点

优点:

  • 灵活性:脚本语言的引入使得Java应用能够动态修改行为,增加了灵活性。
  • 简化开发:无需重新编译整个Java应用,可以动态执行脚本。
  • 多语言支持:能够使用多种脚本语言,适应不同开发者的需求。

缺点:

  • 性能问题:执行脚本语言可能比直接执行Java代码慢,尤其是当脚本频繁执行时。
  • 维护性问题:使用脚本时,可能会增加代码的复杂性,特别是当脚本代码没有很好地组织和文档化时。
  • 调试困难:脚本代码的调试相对困难,尤其是当脚本与Java代码紧密集成时。

9. 总结

JSR223提供了一个标准的接口来将脚本语言集成到Java应用中,支持多个脚本引擎和多种脚本语言的调用。它可以极大地提升Java应用的灵活性和扩展性,尤其适用于动态修改应用行为的场景。然而,使用JSR223时也要注意性能和维护性问题。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/888228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无序抓取系列(一)

文章目录 一 摘要 二 资源 三 内容 一 摘要 最近&#xff0c;已经提出了许多抓取检测方法&#xff0c;这些方法可用于直接从传感器数据中定位机器人抓取配置&#xff0c;而无需估计物体姿态。其基本思想是将抓握感知视作计算机视觉中的对象检测。这些方法将噪声和部分遮挡的…

论文阅读:Deep divergence-based approach to clustering

论文地址&#xff1a;main.pdf (sciencedirectassets.com) 摘要 深度学习研究中的一个有前景的方向是通过优化判别损失函数&#xff0c;学习表示并同时发现无标签数据中的聚类结构。与监督式深度学习不同&#xff0c;这一研究方向尚处于起步阶段&#xff0c;如何设计和优化合适…

关于单片机的原理与应用!

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///目前正在学习C&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于单片…

Flink四大基石之CheckPoint(检查点) 的使用详解

目录 一、Checkpoint 剖析 State 与 Checkpoint 概念区分 设置 Checkpoint 实战 执行代码所需的服务与遇到的问题 二、重启策略解读 重启策略意义 代码示例与效果展示 三、SavePoint 与 Checkpoint 异同 操作步骤详解 四、总结 在大数据流式处理领域&#xff0c;Ap…

字典树TRIE

模板 模板总共分为两部分 插入一个字符串查找一个字符串 int idx 0; int trie[3000010][150]; int ans[3000010];##原理 trie[上节点编号][下方连接的字母] 下方连接的字母的节点编号 trie[0][0]1;trie[0][1]5; trie[1][1]2; trie[2][1]4;trie[2][2]3; trie[5][2]6; tri…

【MySQL-6】MySQL的复合查询

1. 整体学习的思维导图 2. 回顾基本查询 使用scott数据库中的表&#xff0c;完成以下查询&#xff1a; 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J mysql> select * from emp where (sal>500 or jobMANAGER) and ename …

STL算法之其它算法_中

目录 lower_bound(应用于有序区间) upper_bound&#xff08;应用于有序区间&#xff09; binary_search&#xff08;应用于有序区间&#xff09; next_permutation prev_permutation lower_bound(应用于有序区间) 这是二分查找(binary search)的一种版本&#xff0c;试图在…

[高阶数据结构六]最短路径算法

1.前言 最短路径算法是在图论的基础上讲解的&#xff0c;如果你还不知道图论的相关知识的话&#xff0c;可以阅读下面几篇文章。 [高阶数据结构四] 初始图论_初始图结构-CSDN博客 [高阶数据结构五] 图的遍历和最小生成树_图的遍历和生成树求解-CSDN博客 本章重点&#xff1a;…

uniapp:封装商品列表为组件并使用

封装商品列表为组件并使用 商品组件封装 <template><!-- 商品列表 --><view class"goods_list"><view class"goods_item" v-for"item in goods" :key"item.id"><image :src"item.img_url">…

【AI系统】LLVM 架构设计和原理

LLVM 架构设计和原理 在上一篇文章中&#xff0c;我们详细探讨了 GCC 的编译过程和原理。然而&#xff0c;由于 GCC 存在代码耦合度高、难以进行独立操作以及庞大的代码量等缺点。正是由于对这些问题的意识&#xff0c;人们开始期待新一代编译器的出现。在本节&#xff0c;我们…

【C语言】结构体(二)

一&#xff0c;结构体的初始化 和其它类型变量一样&#xff0c;对结构体变量可以在定义时指定初始值 #include <stdio.h> #include <stdlib.h> struct books // 结构体类型 {char title[50];char author[50]; //结构体成员char subject[100];int book_id; }…

四、初识C语言(4)

一、作业&#xff1a;static修饰局部变量 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> //作业&#xff1a;static修饰局部变量 int sum (int a) {int c 0;static int b 3;c 1;b 2;return (abc); } int main() {int i 0;int a …

Linux 中的 ls 命令:从使用到源码解析

ls 命令是 Linux 系统中最常用和最基本的命令之一。下面将深入探讨 ls 命令的使用方法、工作原理、源码解析以及实际应用场景。 1. ls 命令的使用** ls 命令用于列出目录内容&#xff0c;显示文件和目录的详细信息。 1.1 基本用法 ls [选项] [文件或目录]例如&#xff1a; …

The selected directory is not a valid home for Go SDK

在idea里配置go语言的环境时&#xff0c;选择go语言的安装目录&#xff0c;一直提示这个 The selected directory is not a valid home for Go SDK后来查了一下&#xff0c;发现原来idea识别不出来 需要改一下配置文件&#xff0c;找到go环境的安装目录&#xff0c;我是默认安…

Leetcode581. 最短无序连续子数组(HOT100)

链接 我的代码&#xff1a; class Solution { public:int findUnsortedSubarray(vector<int>& nums) {vector<int> res nums;sort(res.begin(),res.end());int l 0,r nums.size()-1;while(nums[l]res[l]){l;if(lnums.size()){return 0;}}while(nums[r]res…

SQL优化与性能——数据库事务管理

数据库事务管理是数据库系统中至关重要的一部分&#xff0c;确保了数据的一致性、完整性、可靠性和隔离性。尤其在高并发、高负载的系统中&#xff0c;事务管理的设计和实现直接影响到系统的稳定性和性能。本章将详细探讨以下内容&#xff1a;事务的ACID特性、使用 BEGIN、COMM…

【Robocasa】Code Review

文章目录 OverviewalgoInitializationImportant Class MethodsTrain LoopTest Time ConfigsdemoConfig FactoryConfig StructureConfig Locking默认锁定状态配置修改的上下文管理器 dataset示例数据集对象参数说明 model基础模块EncoderCoreVisualCoreScanCore随机化器 (Random…

【单细胞数据库】癌症单细胞数据库CancerSEA

数据库地址&#xff1a;home (hrbmu.edu.cn) Cite Huating Yuan, Min Yan, Guanxiong Zhang, Wei Liu, Chunyu Deng, Gaoming Liao, Liwen Xu, Tao Luo, Haoteng Yan, Zhilin Long, Aiai Shi, Tingting Zhao, Yun Xiao, Xia Li, CancerSEA: a cancer single-cell state atlas…

React 的学习记录一:与 Vue 的相同点和区别

目录 一、学习目标 二、学习内容1️⃣——React的特点 1.组件化设计 2.单向数据流 3.声明式 UI 4.虚拟 DOM 5.Hooks 6.JSX 7.React Native 三、React与vue的比较总结 四、总结 一、学习目标 时间&#xff1a;两周 内容&#xff1a; React的特点React的入门React的…

数据库管理-第267期 23ai:Oracle Data Redaction演示(20241128)

数据库管理267期 2024-11-286 数据库管理-第267期 23ai&#xff1a;Oracle Data Redaction演示&#xff08;20241128&#xff09;1 示例表及数据2 创建编校策略2.1 名字全编校2.2 电话部分编校 3 DML演示3.1 场景13.2 场景2 总结 数据库管理-第267期 23ai&#xff1a;Oracle Da…