您现在的位置是:首页 > 文章详情

JDK1.8 nashorn 引擎使用

日期:2019-05-25点击:545

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

在清算项目的计算模块使用 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 方法。

原文链接:https://yq.aliyun.com/articles/703677
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章