· 基本介绍

现在需求是想实现一种既支持算术运算又支持逻辑运算的表达式,网上找了好多资料,大多都是以下情况:

     -> 基于栈或队列来实现基本的算术运算

     -> 基于模板引擎(js、Nashorn、javascript等)

· 存在问题

-> 底层JS引擎计算时会默认把 true 转化为1 ,false转化为0 (解决: 分支思想)

-> 对于&&、|| 结尾的字符串表达式并不报错,其会直接删除, 判断为合理(解决: 添加校验逻辑)

· 实现思路

基于JS引擎实现布尔和四则运算的混合运算_java

基于JS引擎实现布尔和四则运算的混合运算_运算符_02

· 实现过程

1、 使用前提: Java项目中引入依赖 jep 如下所示

<dependency>
  <groupId>jep</groupId>
  <artifactId>jep</artifactId>
  <version>2.24</version>
</dependency>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

2、基于JS引擎拆解执行逻辑(思想: 采用归并思想)

import com.monitor.common.exception.ServiceException;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Yaojinge
 * @Description : 表达式计算工具类
 * @date 2024/8/31
 */
public class ExpressionUtil {
    /**
     * 逻辑运算符 ||
     */
    static final String EXPRESSION_OR="||";
    /**
     * 逻辑运算符 &&
     */
    static final String EXPRESSION_AND="&&";
    /**
     * 逻辑运算符 &
     */
    static final String EXPRESSION_SINGLE_AND="&";

    /**
     * 逻辑运算符 |
     */
    static final String EXPRESSION_SINGLE_OR="|";

    /**
     * 正则匹配 ||
     */
    static final String REGULAR_MATCH_OR="\\|\\|";
    /**
     * 正则表达式匹配中文字符串
     */
    static final String PATTERN_CHINESE = "[\\u4e00-\\u9fa5]+";
    /**
     * 正表达式,匹配单独的 = ,而非 ===、==
     */
    static final String PATTERN_EQUAL = "\\b=\\b";
    /**
     * 错误符号组合列表
     */
    static final String[] COMBINE_LIST = {"*true", "true*", "/true", "true/", "+true", "true+", "-true", "true-",
            "/true", "true/", "%true", "%false", "false%", "true%", "*false", "false*", "/false", "false/", "+false", "false+", "-false", "false-",
            ">true", "<true", ">false", "<false", ">=true", "<=true", ">=false", "<=false"};
    /**
     * 暂不支持符号列表
     */
    final static String[] SYMBOL_LIST = {"++","--", ">>","<<",  ">>>", "^", "[", "]", "{", "}", "?:", "instanceof", "+=", "-=", "*=",
            "/=", "%=", ">>=", "<<=", ">>>=", "&=", "|=", "^=", "&&=", "||=", "?:"};
    /**
     * 非法字符列表(待完善)
     */
    final static String[] ILLEGAL_LIST = {"@", "#", "$", "~", "null"};
    /**
     * 布尔运算符集合
     */
    final static Set<String> BOOLEAN_SET = new HashSet<>(Arrays.asList("true", "false"));

    /**
     * 表达式校验和计算
     * @param expression 表达式
     * @return 计算结果
     */
    public static Object calculateExpression(String expression) {
        // 非空校验
        if (expression == null || expression.length() == 0) {
            throw new ServiceException("表达式不能为空!");
        }
        // 去除空字符
        expression = expression.replace(" ", "");
        // 排除暂不支持的运算符
        checkSymbols(expression);
        // 排除非法运算符组合
        checkLegality(expression);
        // 创建JS引擎
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        // 统计左右括号个数
        char[] array = expression.toCharArray();
        int leftCount = 0,rightCount=0;
        for (char c : array) {
            if (c == '(') {
                leftCount++;
            } else if (c == ')') {
                rightCount++;
            }
        }
        // 根据左右括号的个数执行对应的逻辑
        return getResult(expression, engine, leftCount, rightCount);
    }

    /**
     * 根据左右括号的个数执行对应的计算逻辑
     * @param expression 表达式
     * @param engine JS引擎
     * @param leftCount 左括号个数
     * @param rightCount 右括号个数
     * @return 计算结果
     */
    private static Object getResult(String expression, ScriptEngine engine, int leftCount, int rightCount) {
        Object result = null;
        if (leftCount == 0 && rightCount == 0) {
            result = attainOutcome(expression, engine);
        } else if (leftCount != rightCount) {
            throw new ServiceException("表达式左右括号数量不匹配!");
        } else {
            boolean flag = false;
            char[] charArray = expression.toCharArray();
            for (int i = 0; i < leftCount; i++) {
                int leftIndex = 0,rightIndex = 0;
                // 左括号找最右侧的位置
                for (int j = 0; j < charArray.length; j++) {
                    if (charArray[j] == '(') {
                        leftIndex = j;
                    }
                }
                // 根据左括号位置找离其最近的右括号位置
                for (int j = leftIndex; j < charArray.length; j++) {
                    if (charArray[j] == ')') {
                        rightIndex = j;
                        break;
                    }
                }
                // 取出括号中算式进行计算
                if (rightIndex != 0 && (rightIndex > leftIndex)) {
                    // 拼接字符串
                    String leftString = expression.substring(0, leftIndex);
                    String middleString = expression.substring(leftIndex + 1, rightIndex);
                    String rightString = expression.substring(rightIndex + 1);
                    // 判断是否还需要再次通过JS引擎计算
                    boolean condition = (leftString.length() > 0 || rightString.length() > 0);
                    if ((i == leftCount - 1) || condition) {
                        // 若是还有其他算式,再执行一次计算逻辑
                        flag = true;
                    }
                    // 将中间的字符串放入到JS中进行计算
                    result = attainOutcome(middleString, engine);
                    // 执行完成后,拼接结果,并校验合法性
                    expression = leftString + result.toString() + rightString;
                    checkLegality(expression);
                    // 校验通过将表达式切分成字符数组
                    charArray= expression.toCharArray();
                } else if ((leftIndex > rightIndex)) {
                    throw new ServiceException("表达式括号位置顺序错误!");
                }
            }
            if (flag) {
                // 将最后一次的计算也放入到情况一中执行
                result = attainOutcome(expression, engine);
            }
        }
        return result;
    }

    /**
     * 检验表达式中是否存在暂不支持的字符
     *
     * @param expression 表达式
     */
    private static void checkSymbols(String expression) {
        for (String s : SYMBOL_LIST) {
            if (expression.contains(s)) {
                throw new ServiceException("暂不支持该表达式中的<" + s + ">字符运算");
            }
        }
    }

    /**
     * 过滤非法字符
     *
     * @param expression 表达式
     */
    private static void filterIllegalSymbols(String expression) {
        for (String item : ILLEGAL_LIST) {
            if (expression.contains(item)) {
                throw new ServiceException("表达式中存在非法字符<" + item + ">,请检查");
            }
        }
    }

    /**
     * 校验表达式合法性
     * @param expression 表达式
     */
    private static void checkLegality(String expression) {
        // 过滤运算符 | & =
        if (expression.matches(PATTERN_EQUAL)) {
            throw new ServiceException("底层引擎不支持=运算,请修改");
        } else if (containsChinese(expression)) {
            throw new ServiceException("表达式中存在中文字符,请修改");
        }
        // 非法字符过滤
        filterIllegalSymbols(expression);
        // 表达式前后缀过滤(&&、||)
        boolean condition = expression.startsWith(EXPRESSION_OR) || expression.endsWith(EXPRESSION_OR);
        boolean condition1 = expression.startsWith(EXPRESSION_AND) || expression.endsWith(EXPRESSION_AND);
        if (condition1 || condition) {
            throw new ServiceException("表达式前后缀不符合运算规则,请检查");
        }
        // 错误组合过滤
        for (String s : COMBINE_LIST) {
            if (expression.contains(s)) {
                throw new ServiceException("<" + s + ">不符合运算规则,请检查");
            }
        }
    }

    /**
     * 获取计算结果
     * @param expression 表达式
     * @param engine     JS引擎
     * @return 操作结果
     */
    private static Object attainOutcome(String expression, ScriptEngine engine) {
        Object result = null;
        // 剪枝处理(表达式以||或&&开头或结尾)
        boolean condition = expression.startsWith(EXPRESSION_OR) || expression.endsWith(EXPRESSION_OR);
        boolean condition1 = expression.startsWith(EXPRESSION_AND) || expression.endsWith(EXPRESSION_AND);
        if (condition1 || condition) {
            throw new ServiceException("表达式中&&或||两侧存在空值,请检查");
        }
        // 判断字符串中是否含有 || 符
        if (expression.contains(EXPRESSION_OR)) {
            try {
                // 根据||符号进行拆分成字符串数组
                String[] strList = expression.split(REGULAR_MATCH_OR);
                for (int i = 0; i < strList.length; i++) {
                    // 遍历每个字符数组
                    if (strList[i].contains(EXPRESSION_AND)) {
                        // 存在&&符号
                        String[] list = strList[i].split(EXPRESSION_AND);
                        int amount = list.length;
                        if (amount > 0) {
                            int count = calculateAndCollect(engine, list);
                            //条件过滤及拼接
                            if (count != 0 && count == amount) {
                                int total = 0;
                                StringBuilder sb = new StringBuilder();
                                for (int j = 0; j < list.length; j++, total++) {
                                    if (BOOLEAN_SET.contains(list[j].trim()) && (j != list.length - 1)) {
                                        sb.append(list[j]).append(EXPRESSION_AND);
                                    } else if (BOOLEAN_SET.contains(list[j].trim()) && j == list.length - 1) {
                                        sb.append(list[j]);
                                    } else {
                                        throw new ServiceException(EXPRESSION_AND + "运算符两侧存在非布尔值,表达式错误,请检查");
                                    }
                                }
                                if (total != 0 && total == amount) {
                                    try {
                                        strList[i] = engine.eval(sb.toString()).toString();
                                    } catch (ScriptException e) {
                                        throw new ServiceException("表达式有误,请检查");
                                    }
                                }
                            }
                        }
                    } else {
                        if(strList[i].contains(EXPRESSION_SINGLE_OR)||strList[i].contains(EXPRESSION_SINGLE_AND)){
                            throw new ServiceException("表达式不支持|或&运算,请检查");
                        }
                        strList[i] = engine.eval(strList[i]).toString();
                    }
                }
                StringBuilder sb = new StringBuilder();
                // 拼接字符串
                for (int i = 0; i < strList.length; i++) {
                    if (i != strList.length - 1 && (BOOLEAN_SET.contains(strList[i].trim()))) {
                        sb.append(strList[i]).append(EXPRESSION_OR);
                    } else if (i == strList.length - 1 && (BOOLEAN_SET.contains(strList[i].trim()))) {
                        sb.append(strList[i]);
                    } else {
                        throw new ServiceException(EXPRESSION_OR + "运算符两侧因数存在非布尔值,表达式错误,请检查");
                    }
                }
                // 执行计算逻辑
                result = engine.eval(sb.toString());
            } catch (ScriptException e) {
                throw new ServiceException("表达式有误,请检查");
            }
        } else if (expression.contains(EXPRESSION_AND)) {
            // 存在&&符号
            String[] list = expression.split(EXPRESSION_AND);
            int amount = list.length;
            if (amount > 0) {
                int count = calculateAndCollect(engine, list);
                // 字符串数组拼接和计算
                if (count != 0 && count == amount) {
                    int total = 0;
                    StringBuilder sb = new StringBuilder();
                    for (int j = 0; j < list.length; j++, total++) {
                        if (BOOLEAN_SET.contains(list[j].trim()) && j != list.length - 1) {
                            // 开始进行拼接
                            sb.append(list[j]).append(EXPRESSION_AND);
                        } else if (BOOLEAN_SET.contains(list[j].trim()) && j == list.length - 1) {
                            // 最后一个,直接拼接即可
                            sb.append(list[j]);
                        } else {
                            throw new ServiceException(EXPRESSION_AND + "运算符两侧存在非布尔值,表达式错误,请检查");
                        }
                    }
                    if (total != 0 && total == amount) {
                        try {
                            result = engine.eval(sb.toString());
                        } catch (ScriptException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        } else {
            // 情况三: 表达式中不存在 (、)、||、&& 等运算符,直接通过JS引擎计算即可
            if (expression.contains(EXPRESSION_SINGLE_OR)||expression.contains(EXPRESSION_SINGLE_AND)){
                throw new ServiceException("表达式不支持|或&运算,请检查");
            }
            try {
                result = engine.eval(expression);
            } catch (ScriptException e) {
                throw new RuntimeException("表达式有误,请检查!");
            }
        }
        return result;
    }

    /**
     * 计算集合中的每个元素位置表达式
     * @param engine JS引擎
     * @param list   表达式集合
     * @return 计数器结果
     */
    private static int calculateAndCollect(ScriptEngine engine, String[] list) {
        int count = 0;
        // 遍历每个字符数组进行单独计算
        for (int j = 0; j < list.length; j++) {
            // 空值校验
            if (list[j] == null || "".equals(list[j])) {
                throw new ServiceException("表达式运算符" + EXPRESSION_AND + "两侧存在空值,请检查");
            }
            if (BOOLEAN_SET.contains(list[j].trim())) {
                count++;
            } else {
                if(list[j].contains("|")||list[j].contains("&")){
                    throw new ServiceException("表达式不支持|或&运算,请检查");
                }
                try {
                    // 单独计算并赋值
                    list[j] = engine.eval(list[j]).toString();
                    count++;
                } catch (ScriptException e) {
                    throw new ServiceException("表达式有误,请检查");
                }
            }
        }
        return count;
    }

    /**
     * 判断字符串是否包含中文
     * @param str 字符串
     * @return 包含中文返回true
     */
    public static boolean containsChinese(String str) {
        Pattern pattern = Pattern.compile(PATTERN_CHINESE);
        Matcher matcher = pattern.matcher(str);
        return matcher.find();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.
  • 293.
  • 294.
  • 295.
  • 296.
  • 297.
  • 298.
  • 299.
  • 300.
  • 301.
  • 302.
  • 303.
  • 304.
  • 305.
  • 306.
  • 307.
  • 308.
  • 309.
  • 310.
  • 311.
  • 312.
  • 313.
  • 314.
  • 315.
  • 316.
  • 317.
  • 318.
  • 319.
  • 320.
  • 321.
  • 322.
  • 323.
  • 324.
  • 325.
  • 326.
  • 327.
  • 328.
  • 329.
  • 330.
  • 331.
  • 332.
  • 333.
  • 334.
  • 335.
  • 336.
  • 337.
  • 338.
  • 339.
  • 340.
  • 341.
  • 342.
  • 343.
  • 344.
  • 345.
  • 346.
  • 347.
  • 348.
  • 349.
  • 350.
  • 351.
  • 352.
  • 353.
  • 354.
  • 355.
  • 356.
  • 357.
  • 358.
  • 359.
  • 360.
  • 361.
  • 362.
  • 363.
  • 364.
  • 365.
  • 366.
  • 367.
  • 368.
  • 369.
  • 370.
  • 371.
  • 372.
  • 373.
  • 374.
  • 375.

测试代码:

/**
 * @author Yaojinge
 * @Description
 * @date 2024/8/31
 */
public class IllegalExpressionTest {
    // 日志对象
    private static final Logger logger = LoggerFactory.getLogger(LegalExpressionTest.class);
    public static void main(String[] args) {
        System.out.println("---------------------------------------------------------------------------非法运算测试--------------------------------------------------");
        // 左右括号位置顺序错误
        logger.info("=>  )1+2( = {}", ExpressionUtil.calculateExpression(")1+2(").toString());

        // 表达式左右括号数量不匹配
        logger.info("=>  )1+2 = {}", ExpressionUtil.calculateExpression(")1+2").toString(  ));

        // 布尔值运算不符合规则
        logger.info("=>  (1>2)+10 = {}", ExpressionUtil.calculateExpression("(1>2)+10").toString());

        // 表达式前后缀不符合运算规则,请检查
        logger.info("=>  || (7>2) = {}", ExpressionUtil.calculateExpression("|| (7>2)").toString());
        logger.info("=>  (7>2) || = {}", ExpressionUtil.calculateExpression("(7>2) ||").toString());
        logger.info("=>  (7>2) && = {}", ExpressionUtil.calculateExpression("(7>2) &&").toString());
        logger.info("=>  &&(7>2) = {}", ExpressionUtil.calculateExpression("&&(7>2)").toString());
        logger.info("=> ((7>2)&&(8>2))&& = {}", ExpressionUtil.calculateExpression("((7>2)&&(8>2))&&").toString());

        // 表达式中&&或||两侧存在空值,请检查(运算表达式直接以 && 或 ||  开头或结尾)
        logger.info("=> ((7>2)&&)&&(8>2) = {}", ExpressionUtil.calculateExpression("((7>2)&&)&&(8>2)").toString());
        logger.info("=> ((7>2)||)&&(8>2) = {}", ExpressionUtil.calculateExpression("((7>2)||)&&(8>2)").toString());

        // 表达式中存在非法字符组合
        logger.info("=>  (1<2)*3 = {}", ExpressionUtil.calculateExpression("(1<2)*3").toString());
        logger.info("=>  (1<2)+3 = {}", ExpressionUtil.calculateExpression("(1<2)+3").toString());
        logger.info("=>  (1<2)-3 = {}", ExpressionUtil.calculateExpression("(1<2)-2").toString());
        logger.info("=>  (1<2)/3 = {}", ExpressionUtil.calculateExpression("(1<2)/3").toString());
        logger.info("=>  (1<2)%3 = {}", ExpressionUtil.calculateExpression("(1<2)<3").toString());

        // 表达式中存在中文字符,请修改
        logger.info("=>  (1<2中文)<3 = {}", ExpressionUtil.calculateExpression("(1<2中文)<3").toString());

        // 表达式不支持|或&运算,请检查
        logger.info("=>  (1|2)||3 = {}", ExpressionUtil.calculateExpression("(1|2)||3").toString());
        logger.info("=>  (1&2)&&3 = {}", ExpressionUtil.calculateExpression("(1&2)&&3").toString());

        // 表达式中存在非法字符<#>,请检查
        logger.info("=>  (1<2)#3 = {}", ExpressionUtil.calculateExpression("(1<2)#3"));
        logger.info("=>  (1<2)@3 = {}", ExpressionUtil.calculateExpression("(1<2)@3"));
        logger.info("=>  (1<2)$3 = {}", ExpressionUtil.calculateExpression("(1<2)$3"));
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
/**
 * @author Yaojinge
 * @Description
 * @date 2024/8/30
 */
public class LegalExpressionTest {
    /**
     * 日志对象
     */
    private static final Logger logger = LoggerFactory.getLogger(LegalExpressionTest.class);
    public static void main(String[] args) {

        //算术运算
        System.out.println("-------------------------------------------------------------------------算术运算-------------------------------------------------------------------");
        logger.info("=>   1+2 = {}", ExpressionUtil.calculateExpression("1+2").toString());
        logger.info("=>   1-2 = {}", ExpressionUtil.calculateExpression("1-2").toString());
        logger.info("=>   1*2 = {}", ExpressionUtil.calculateExpression("1*2").toString());
        logger.info("=>   1/2 = {}", ExpressionUtil.calculateExpression("1/2").toString());
        logger.info("=>   1%2 = {}", ExpressionUtil.calculateExpression("1%2").toString());

        // 复杂算术运算
        System.out.println("-------------------------------------------------------------------------复杂算术运算------------------------------------------------------------------");
        logger.info("=>   1+2*3 = {}", ExpressionUtil.calculateExpression("1+2*3").toString());
        logger.info("=>   1+2*3/4 = {}", ExpressionUtil.calculateExpression("1+2*3/4").toString());
        logger.info("=>   1+2*(3/4) = {}", ExpressionUtil.calculateExpression("1+2*(3/4)").toString());
        logger.info("=>   1+2*(3/4)*5 = {}", ExpressionUtil.calculateExpression("1+2*(3/4)*5").toString());
        logger.info("=>   1+2*(3/4)*5%6 = {}", ExpressionUtil.calculateExpression("1+2*(3/4)*5%6").toString());
        logger.info("=>   1+2*(3/4)*5%6+7-8/9*10%11 = {}", ExpressionUtil.calculateExpression("1+2*(3/4)*5%6+7-8/9*10%11").toString());
        logger.info("=>   (32+21)%100 ={}", ExpressionUtil.calculateExpression("(32+21)%100").toString());
        logger.info("=>   4.2-(32+21)%100 = {}", ExpressionUtil.calculateExpression("4.2-(32+21)%100").toString());
        logger.info("=>   (32+21)/100 = {}", ExpressionUtil.calculateExpression("(32+21)/100").toString());
        logger.info("=>   4.1+(32+21)/100 = {}", ExpressionUtil.calculateExpression("4.1+(32+21)/100").toString());

        //关系运算
        System.out.println("--------------------------------------------------------------------------关系运算------------------------------------------------------------------");
        logger.info("=>   1>2 = {}", ExpressionUtil.calculateExpression("1>2").toString());
        logger.info("=>   1<2 = {}", ExpressionUtil.calculateExpression("1<2").toString());
        logger.info("=>   1>=2 = {}", ExpressionUtil.calculateExpression("1>=2").toString());
        logger.info("=>   1<=2 = {}", ExpressionUtil.calculateExpression("1<=2").toString());
        logger.info("=>   1==2 = {}", ExpressionUtil.calculateExpression("1==2").toString());
        logger.info("=>   1===2 = {}", ExpressionUtil.calculateExpression("1===2").toString());
        logger.info("=>   1!=2 = {}", ExpressionUtil.calculateExpression("1!=2").toString());
        logger.info("=>   1!==2 = {}", ExpressionUtil.calculateExpression("1!==2").toString());

        // 复杂关系运算
        System.out.println("---------------------------------------------------------------------------复杂关系运算------------------------------------------------------------------");
        logger.info("=>   1>2&&2>3 = {}", ExpressionUtil.calculateExpression("1>2&&2>3").toString());
        logger.info("=>   1>2&&2<3 = {}", ExpressionUtil.calculateExpression("1>2&&2<3").toString());
        logger.info("=>   1>2||2<3 = {}", ExpressionUtil.calculateExpression("1>2||2<3").toString());
        logger.info("=>   (1>2||2<3)&&3>4 = {}", ExpressionUtil.calculateExpression("(1>2||2<3)&&3>4").toString());
        logger.info("=>   (1>2||2<3)&&3<4 = {}", ExpressionUtil.calculateExpression("(1>2||2<3)&&3<4").toString());
        logger.info("=>   (1>2||2<3)&&(3>4||4<5) = {}", ExpressionUtil.calculateExpression("(1>2||2<3)&&(3>4||4<5)").toString());
        logger.info("=>   (1>2||2<3)&&(3<4||4>5) = {}", ExpressionUtil.calculateExpression("(1>2||2<3)&&(3<4||4>5)").toString());

        //逻辑运算
        System.out.println("---------------------------------------------------------------------------逻辑运算------------------------------------------------------------------");
        logger.info("=>   true&&false = {}", ExpressionUtil.calculateExpression("true&&false").toString());
        logger.info("=>   true||false = {}", ExpressionUtil.calculateExpression("true||false").toString());
        logger.info("=>   !true = {}", ExpressionUtil.calculateExpression("!true").toString());
        logger.info("=>   !(7>3) = {}", ExpressionUtil.calculateExpression("!(7>3)"));

        // 复杂逻辑运算
        System.out.println("---------------------------------------------------------------------------复杂逻辑运算------------------------------------------------------------------");
        logger.info("=>   ((6>1)||(true&&(6<2))&&((4<7)||(6>=3))) = {}", ExpressionUtil.calculateExpression("((6>1)||(true&&(6<2))&&((4<7)||(6>=3)))"));

        // 逻辑和算术混合运算
        System.out.println("---------------------------------------------------------------------------逻辑和算术混合运算-----------------------------------------------------");
        logger.info("=>   (1+2>3&&4/2==2) = {}", ExpressionUtil.calculateExpression("(1+2>3&&4/2==2)"));
        logger.info("=>   false&&(4/2==2) = {}", ExpressionUtil.calculateExpression("false&&(4/2==2)"));
        logger.info("=>   true||4/2==2 = {}", ExpressionUtil.calculateExpression("true||4/2==2"));
        logger.info("=>   (1+2>3&&4/2==2)||(false&&(4/2==2)) = {}", ExpressionUtil.calculateExpression("(1+2>3&&4/2==2)||(false&&(4/2==2))"));
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.

测试结果(合理):

-------------------------------------------------------------------------算术运算-------------------------------------------------------------------
18:29:05.084 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1+2 = 3
18:29:05.095 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1-2 = -1
18:29:05.102 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1*2 = 2
18:29:05.109 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1/2 = 0.5
18:29:05.116 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1%2 = 1
-------------------------------------------------------------------------复杂算术运算------------------------------------------------------------------
18:29:05.122 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1+2*3 = 7
18:29:05.127 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1+2*3/4 = 2.5
18:29:05.133 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1+2*(3/4) = 2.5
18:29:05.140 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1+2*(3/4)*5 = 8.5
18:29:05.147 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1+2*(3/4)*5%6 = 2.5
18:29:05.153 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1+2*(3/4)*5%6+7-8/9*10%11 = 0.6111111111111107
18:29:05.160 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (32+21)%100 =53
18:29:05.166 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   4.2-(32+21)%100 = -48.8
18:29:05.171 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (32+21)/100 = 0.53
18:29:05.176 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   4.1+(32+21)/100 = 4.63
--------------------------------------------------------------------------关系运算------------------------------------------------------------------
18:29:05.184 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1>2 = false
18:29:05.188 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1<2 = true
18:29:05.192 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1>=2 = false
18:29:05.195 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1<=2 = true
18:29:05.199 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1==2 = false
18:29:05.202 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1===2 = false
18:29:05.207 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1!=2 = true
18:29:05.212 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1!==2 = true
---------------------------------------------------------------------------复杂关系运算------------------------------------------------------------------
18:29:05.218 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1>2&&2>3 = false
18:29:05.226 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1>2&&2<3 = false
18:29:05.233 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   1>2||2<3 = true
18:29:05.242 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (1>2||2<3)&&3>4 = false
18:29:05.249 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (1>2||2<3)&&3<4 = true
18:29:05.258 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (1>2||2<3)&&(3>4||4<5) = true
18:29:05.267 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (1>2||2<3)&&(3<4||4>5) = true
---------------------------------------------------------------------------逻辑运算------------------------------------------------------------------
18:29:05.271 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   true&&false = false
18:29:05.277 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   true||false = true
18:29:05.282 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   !true = false
18:29:05.289 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   !(7>3) = false
---------------------------------------------------------------------------复杂逻辑运算------------------------------------------------------------------
18:29:05.311 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   ((6>1)||(true&&(6<2))&&((4<7)||(6>=3))) = true
---------------------------------------------------------------------------逻辑和算术混合运算-----------------------------------------------------
18:29:05.321 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (1+2>3&&4/2==2) = false
18:29:05.329 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   false&&(4/2==2) = false
18:29:05.340 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   true||4/2==2 = true
18:29:05.350 [main] INFO com.jin.demofunction.test.LegalExpressionTest - =>   (1+2>3&&4/2==2)||(false&&(4/2==2)) = false

Process finished with exit code 0
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
· 总结

  主要实现了基于JS表达式引擎的逻辑和算术混合表达式的计算,目前的封装类支持的运算符如下:

  -  小括号 :  ()

  -  基本四则运算符: +、-、*、/、%

  -  判断:  >、<、>= 、<=、!=、==

  -  布尔运算符:  && 、|| 、!

各位小伙伴测试过程若是遇到表达式不合理的情况,请在评论区给我留言,大家一起进步 !!