安卓(Android)或者Java使用rhino实现任意字符串表达式计算
本文连接:https://www.cnblogs.com/muphy/p/15253488.html
Java使用rhino
引入依赖包
<!-- https://mvnrepository.com/artifact/org.mozilla/rhino --> <dependency> <groupId>org.mozilla</groupId> <artifactId>rhino</artifactId> <version>1.7.13</version> </dependency>
初始rhino的Context
Context.enter();
安卓系统使用rhino不太一样,安卓使用参考:https://github.com/F43nd1r/rhino-android
引入依赖包
implementation ‘com.faendir.rhino:rhino-android:1.6.0‘ //implementation group: ‘org.mozilla‘, name: ‘rhino‘, version: ‘1.7.13‘
初始化rhino的Context
//这里参数context使用Android的Context new RhinoAndroidHelper(context).enterContext()
AndroidContextHolder.java
import android.content.Context; public class AndroidContextHolder { private static Context context; public static Context getContext() { return context; } public static void setContext(Context context) { AndroidContextHolder.context = context; } }
CalculateUtils.java
//package com.moefon.power.spring.util; import org.mozilla.javascript.Context; import org.mozilla.javascript.Function; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.Undefined; import java.util.Stack; /** * 将字符串转计算公式 * Object r1 = evaluate("function f(){var x = 5; y = 455; var m = {‘x‘:x,‘y‘:y}; return x}; var i = f();"); // Undefined * Object r2 = evaluate("function f(){var x = 5; y = 455; var m = {‘x‘:x,‘y‘:y}; return x}; var i = f(); i;"); // Integer:5 * Object r3 = evaluate("var f = function(){var x = 5; var m = {‘x‘:x,‘y‘:55}; return m}; var i = f();", "i"); // NativeObject:{‘x‘:x,‘y‘:y} * Object r4 = evaluate("var f = function(v){var x = 5; var m = {‘x‘:x,‘y‘:v}; return m;};", "f", 1); // NativeObject:{‘x‘:x,‘y‘:y} * Object r5 = evaluate("var f = function(v){var x = 5; var m = {‘x‘:x,‘y‘:v}; return x + v;};", "f", 1); // Double:5 * * AndroidContextHolder.getContext() 表示安卓启动的时候记得设置activity或者application * * @author: 若非 * @date: 2021/9/9 20:43 */ public class CalculateUtils { /** * 将字符串转计算公式 {@code evaluate(7+ +55 + +5 * (2-5)) } * * @param js * @return: 计算结果 * @author: 若非 * @date: 2021/9/9 20:43 */ public static <T> T evaluate(String js) { Context ctx = new RhinoAndroidHelper(AndroidContextHolder.getContext).enterContext(); Scriptable scope = ctx.initStandardObjects(); //初始化本地对象 T result = null; try { Object o = ctx.evaluateString(scope, js, "", 1, null); if (o != Scriptable.NOT_FOUND && !(o instanceof Undefined)) { result = (T) o;//执行 } } catch (Exception e) { e.printStackTrace(); } return result; } /** * 执行JS代码 * * @param js * @param resultName scope中获取返回参数名称 * @return: js对象 计算结果 * @author: 若非 * @date: 2021/9/9 20:43 */ public static <T> T evaluate(String js, String resultName) { Context ctx = new RhinoAndroidHelper(AndroidContextHolder.getContext()).enterContext(); Scriptable scope = ctx.initStandardObjects(); //初始化本地对象 T result = null; try { ctx.evaluateString(scope, js, "", 1, null);//执行 } catch (Exception e) { e.printStackTrace(); } Object o = scope.get(resultName, scope); if (o != Scriptable.NOT_FOUND && !(o instanceof Undefined)) { result = (T) o;//执行 } return result; } /** * 执行JS代码 * * @param js js代码 * @param functionName js方法名称 * @param functionParams js方法参数 * @return js对象 * @author: 若非 * @date: 2021/9/9 20:43 */ public static <T> T evaluate(String js, String functionName, Object... functionParams) { Context ctx = new RhinoAndroidHelper(AndroidContextHolder.getContext()).enterContext(); ctx.setOptimizationLevel(-1); T result = null; try { Scriptable scope = ctx.initStandardObjects(); ctx.evaluateString(scope, js, null, 1, null); Function function = (Function) scope.get(functionName, scope); Object o = function.call(ctx, scope, scope, functionParams); if (o != Scriptable.NOT_FOUND && !(o instanceof Undefined)) { result = (T) o;//执行 } } catch (Exception e) { e.printStackTrace(); } return result; } /** * 加减乘除计算 使用包装类方便取值 * * @param expression * @return * @author: 若非 * @date: 2021/9/9 20:43 * @see this#evaluate * @deprecated {@code this.evaluate} */ @Remind(deprecated = true, notice = "请使用evaluate方法来进行表达式计算,这里只支持+-*/") public static Double calculationResult(String expression) { char[] chars = expression.toCharArray(); Stack<String> stack = new Stack<>(); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < chars.length; i++) { switch (chars[i]) { case ‘+‘: case ‘-‘: stack.push(stringBuilder.toString()); stack.push(String.valueOf(calculationResult(stack))); stack.push(chars[i] + ""); stringBuilder = new StringBuilder(); break; case ‘*‘: case ‘/‘: stack.push(stringBuilder.toString()); stack.push(chars[i] + ""); stringBuilder = new StringBuilder(); break; default: stringBuilder.append(chars[i]); } } stack.push(stringBuilder.toString()); Double v = calculationResult(stack); return v; } /** * 加减乘除计算 使用包装类方便取值 * * @param stack * @return 执行结果 * @author: 若非 * @date: 2021/9/9 20:43 * @see this#evaluate * @deprecated {@code this.evaluate} */ private static Double calculationResult(Stack<String> stack) { double res = Double.parseDouble(stack.pop()); while (!stack.empty()) { String opt = stack.pop(); double second = Double.parseDouble(stack.pop()); res = calculation(res, second, opt.charAt(0)); } return res; } /** * 加减乘除计算 使用包装类方便取值 * * @param res * @param x * @param opt * @return 执行结果 * @author: 若非 * @date: 2021/9/9 20:43 * @see this#evaluate * @deprecated {@code this.evaluate} */ private static Double calculation(double res, double x, char opt) { switch (opt) { case ‘+‘: return res + x; case ‘-‘: return x - res; case ‘*‘: return res * x; case ‘/‘: if (x < 0.0000000001f) { return Double.MAX_VALUE; } return x / res; default: return res; } } }