JDK1.8 nashorn 引擎使用

简介: 整理了近期在项目上做的一些技术研究,希望与大家共同探讨交流。 在清算项目的计算模块使用 jdk 1.8 自带的 js 引擎 nashorn 做运算。 使用过程对 nashorn 做了一些简单的测试。

整理了近期在项目上做的一些技术研究,希望与大家共同探讨交流。

在清算项目的计算模块使用 jdk 1.8 自带的 js 引擎 nashorn 做运算。 使用过程对 nashorn 做了一些简单的测试。

使用 nashorn 编译 js 后 执行 invokeFunction 计算 ,一个简单的逻辑判断 加上一个简单的乘法运算 循环执行100w次总耗时约为600~700ms

使用 mozilla 的 rhino js引擎, 编译 js 后 执行 func.call 计算 ,总耗时约为 1400ms 左右。

nashorn 中 eval 方法编译 js 耗时很大, 实际应用时需要进行缓存处理。

除此之外, 使用 nashorn 过程一直调用不到内部的 js 方法。

这里记录下这次的使用方式

public class LiquidationUtil {
    private static Logger logger = LoggerFactory.getLogger(LiquidationUtil.class);
     
    public static final String _expression = "_expression";
    public static final String _conditions = "_conditions";
    // 生成清算规则的计算对象
    public static Invocable  generateLiquidationFuction(String conditions,String expressionMark,String expressionParam) throws ScriptException, NoSuchMethodException {//Liquidation
        StringBuffer sb = new StringBuffer(128);
        if(StringUtils.isEmpty(conditions))
            conditions = "true";
         
        sb.append("var ").append(_conditions).append(" = function (m,o) {")
            .append("\nreturn ").append(_conditions).append("(m,o,null);\n")
        .append("};\n");
        sb.append("var ").append(_expression).append(" = function (m,o) {")
            .append("\nreturn ").append(_expression).append("(m,o,null);\n")
        .append("};\n");
         
        // 条件
        sb.append("var ").append(_conditions).append(" = function (m,o,jh) {")
            .append("\nreturn ").append(conditions).append(";\n")
        .append("};\n");
         
         
        String expressionJs = expressionMap.get(expressionMark);
        // 计算
        sb.append("var ").append(_expression).append(" = function (m,o,jh) {")
            .append("\nvar result=null;\n")
            .append("\n var ").append(expressionParam).append(";\n")
            .append("\n").append(expressionJs).append(";\n")
            .append("\nreturn result;\n")
        .append("};");
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");//nashorn javascript
        engine.eval(sb.toString());
        return (Invocable) engine;
    }
     
     
     
     
    private static final Map<String, String> expressionMap = new HashMap<String, String>();
    static {
        try {
            String path = Thread.currentThread().getContextClassLoader().getResource("liquidation_script").getFile();
            logger.info("加载清算规则js脚本 path:{}", path);
            File dir = new File(path);
            for(File script : dir.listFiles()) {
                String fileName = script.getName();
                String filePath = script.getAbsolutePath();
                logger.info("加载清算规则脚本 mark:{}\tfilePath:{}",fileName, filePath);
                expressionMap.put(fileName.substring(0, fileName.length()-3), readFileContent(filePath));
            }
        } catch (IOException e) {
            logger.error("初始化算费规则脚本出错", e);
        }
    }
    public static String readFileContent(String uri) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(uri));
        String line = "";
        StringBuffer buffer = new StringBuffer();
        while ((line = br.readLine()) != null) {
            buffer.append(line).append("\n");
        }
        String fileContent = buffer.toString();
        return fileContent;
    }
}
调用:
            jsInvocable = (Invocable)LiquidationUtil.generateLiquidationFuction(conditionsJs, expressionMark, expressionParam);// 对 invocable 缓存
            result = jsInvocable.invokeFunction(_conditions, mapping, orderInfo);

js 代码的格式为

var func1 = function(param1, param2){

...

}

var func2 = function(param1, param2){

...

}

对这段字符串执行 eval, 得到 Invocable ,

然后可以执行 Invocable.invokeFunction("func1", param1, param2) 调用 js 方法。

目录
相关文章
|
存储 SQL Java
数据库TiDB-01.数据库架构概述
TiDB兼容MySQL 5.7协议,支持水平扩容或者缩容的金融级高可用的云原生分布式数据库。
787 2
数据库TiDB-01.数据库架构概述
|
存储 数据安全/隐私保护
Alist ——本地网盘管理器
Alist ——本地网盘管理器
19401 1
|
存储 Java 调度
FileInputStream,FileOutputStream 和 FileReader ,FileWriter 类的基本使用【 File类+IO流知识回顾②】
这篇文章回顾了Java中FileInputStream、FileOutputStream、FileReader和FileWriter类的基本使用方法,包括读取和写入文件的操作,以及字符流和字节流的区别和应用场景。
FileInputStream,FileOutputStream 和 FileReader ,FileWriter 类的基本使用【 File类+IO流知识回顾②】
Next.js 实战 (三):优雅的实现暗黑主题模式
这篇文章介绍了在Next.js中实现暗黑模式的具体步骤。首先,需要安装next-themes库。然后,在/components/ThemeProvider/index.tsx文件中新增ThemeProvider组件,并在/app/layout.tsx文件中注入该组件。如果想要加入过渡动画,可以修改代码实现主题切换时的动画效果。最后,需要在需要的位置引入ThemeModeButton组件,实现暗黑模式的切换。
392 0
Next.js 实战 (三):优雅的实现暗黑主题模式
|
JavaScript 前端开发 安全
前程无忧搜索接口 JS 逆向:阿里系acw_sc__v2和Sign加密
前程无忧搜索接口 JS 逆向:阿里系acw_sc__v2和Sign加密
629 0
|
算法 数据可视化 Java
JAVA规则引擎工具有哪些?
本文对比分析了六种Java规则引擎:Drools、IBM ODM (JRules)、Easy Rules、JBPM、OpenL Tablets以及Apache Camel结合规则组件的应用。Drools是一款功能全面的业务规则管理系统,支持DRL文件定义规则、高效的规则匹配算法、复杂的规则流及决策表,并易于与Java应用集成。IBM ODM (原JRules)提供了强大的规则管理功能,包括Web界面和Eclipse插件定义管理规则、直观的决策表和决策树、REST和Java API集成选项及优化的性能。
2243 3
|
监控 Java UED
Java一分钟之-Spring Cloud Netflix Hystrix:容错管理
【6月更文挑战第9天】Spring Cloud Hystrix是用于微服务容错管理的库,通过断路器模式防止服务雪崩。本文介绍了Hystrix的基本概念,如断路器、线程隔离和fallback机制,并展示了如何快速上手,包括添加依赖、启用注解和编写Hystrix命令。此外,还讨论了常见问题(如断路器打开、资源泄漏和不当的Fallback策略)及其解决方案。通过自定义Hystrix指标监控,可以进一步优化系统性能。理解Hystrix工作原理并适时调整配置,对于构建健壮的微服务至关重要。
366 3
|
监控 Linux 数据库连接
手把手教你从本地到云端:全面解析Blazor应用的部署流程与最佳实践,助你轻松掌握发布Blazor WebAssembly应用到Azure的每一个细节
【8月更文挑战第31天】本文详细介绍了将 Blazor 应用从本地部署到 Azure 的全过程。首先确保已在 Visual Studio 中创建 Blazor WebAssembly 应用,接着清理项目并配置发布选项。然后在 Azure 中创建 App Service 并完成应用部署。最后,配置环境变量、SSL 和监控,确保应用稳定运行。附带示例代码,展示如何加载和使用 Azure 环境变量。通过最佳实践指导,帮助你顺利完成 Blazor 应用的云端部署。
525 0
|
UED 开发者 Python
Python中使用`requests`库进行重定向与超时控制的技术详解
【4月更文挑战第12天】在Web开发中,处理HTTP重定向和请求超时是常见的需求。`requests`库作为Python中处理HTTP请求的利器,提供了丰富的功能来满足这些需求。本文将详细探讨如何在Python中使用`requests`库进行重定向处理和超时控制。
|
SQL 存储 监控
tidb
tidb 练习
2193 0