1 import javax.script.Invocable; 2 import javax.script.ScriptEngine; 3 import javax.script.ScriptEngineManager; 4 import javax.script.ScriptException; 5 import java.util.Map; 6 import java.util.regex.Matcher; 7 import java.util.regex.Pattern; 8 9 public class JavaScriptUtil { 10 11 public static Object calculateRatio(Map<String, Object> column,Map<String, Object> row) throws ScriptException, NoSuchMethodException { 12 ScriptEngineManager manager = new ScriptEngineManager(); 13 ScriptEngine engine = manager.getEngineByName("nashorn"); 14 // 如果还是没有引擎可用,抛出明确异常 15 if (engine == null) { 16 if(column.get("filed") != null){ 17 return row.get(column.get("filed")); 18 } 19 return ""; 20 } 21 // 注入数据到JS环境 22 engine.put("row", row); 23 // 根据引擎类型使用不同的语法 24 String formatter = column.get("formatter").toString(); 25 String converted = "function calculateRatio(row) {"+convertJsForNashorn(formatter)+"}"; 26 engine.eval(converted); 27 // 调用函数 28 Object result = ((Invocable)engine).invokeFunction("calculateRatio", row); 29 return result.toString(); 30 } 31 32 public static void main(String[] args) throws ScriptException, NoSuchMethodException { 33 Map<String, Object> column = Map.of("formatter", "let { Z, V } = row; // Z=计划品, V=检验量 \n" + 34 "if(Z == 0){\n" + 35 " return 0; \n" + 36 "}else{\n" + 37 " return parseFloat((((Z/V) * 100)).toFixed(3));\n" + 38 "}", "V", 100); 39 Map<String, Object> row = Map.of("Z", 20, "V", 100); 40 System.out.println(calculateRatio(column,row)); // 输出 25.0 41 } 42 43 /** 44 * 转换JavaScript代码为Nashorn兼容格式 45 * @param jsCode 原始JavaScript代码 46 * @return 转换后的JavaScript代码 47 */ 48 public static String convertJsForNashorn(String jsCode) { 49 // 1. 转换let/const为var 50 String converted = convertVariableDeclarations(jsCode); 51 52 // 2. 处理解构赋值 53 converted = convertDestructuringAssignments(converted); 54 55 // 3. 其他可能的转换可以在这里添加 56 57 return converted; 58 } 59 60 /** 61 * 将let和const转换为var 62 */ 63 private static String convertVariableDeclarations(String jsCode) { 64 // 替换所有let和const为var,但排除函数声明中的情况 65 String pattern = "(?<!(function\\s+|\\w+\\s*\\.))\\b(let|const)\\b"; 66 return jsCode.replaceAll(pattern, "var"); 67 } 68 69 /** 70 * 处理解构赋值转换为传统赋值 71 */ 72 private static String convertDestructuringAssignments(String jsCode) { 73 // 匹配类似 let { Z, V } = row; 的模式 74 Pattern pattern = Pattern.compile("var\\s*\\{([^}]+)\\}\\s*=\\s*(\\w+)\\s*;"); 75 Matcher matcher = pattern.matcher(jsCode); 76 77 StringBuffer sb = new StringBuffer(); 78 while (matcher.find()) { 79 String variables = matcher.group(1).trim(); 80 String sourceObject = matcher.group(2).trim(); 81 82 // 处理每个解构变量 83 String[] vars = variables.split(","); 84 StringBuilder replacements = new StringBuilder(); 85 86 for (String var : vars) { 87 var = var.trim(); 88 if (var.isEmpty()) continue; 89 90 // 处理可能的别名情况,如 { Z: alias } 91 if (var.contains(":")) { 92 String[] parts = var.split(":"); 93 String original = parts[0].trim(); 94 String alias = parts[1].trim(); 95 replacements.append("var ").append(alias).append("=") 96 .append(sourceObject).append(".").append(original).append(";"); 97 } else { 98 replacements.append("var ").append(var).append("=") 99 .append(sourceObject).append(".").append(var).append(";"); 100 } 101 } 102 103 matcher.appendReplacement(sb, replacements.toString()); 104 } 105 matcher.appendTail(sb); 106 107 return sb.toString(); 108 } 109 }