解决JexlEngine执行where条件时,等号(=)替换成双等号(==)问题

这篇具有很好参考价值的文章主要介绍了解决JexlEngine执行where条件时,等号(=)替换成双等号(==)问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

jexlengine,练习code,Java,java,mysql,数据结构

前言

  • 简单描述一下JexlEngine的用法,使用它可以将一段表达式转成Java代码执行。

问题描述

String WHERE = "app_id=005";

  假设上面的where变量需要传递给JexlEngine调用,由于JexlEngine执行表达式的时候,一个等号(=)是会报语法错误的,需要转成两个等号(==)才能执行,如果后面还有and、or条件拼接,则 and 要转成 &&or 要转成 ||(这一步可转可不转,不过一定不能是大写) 。

String WHERE = "pay_time > ='2019/10/21' and pay_time < = '2019/10/22' and app_id = '001'";

  需求:给出上面的where条件,我们需要将有且仅有一个等号(=)的情况转成两个等号(==),>=和<=无需转换,最后再将and 转成 &&or 要转成 ||

即想要的效果如下:

String WHERE = "pay_time > ='2019/10/21' && pay_time < = '2019/10/22' and app_id == '001'";

思路分析

  我们先使用toCharArray将字符串转换为字符数组,然后根据字符的索引去判断一个等号(=)出现的位置,再进行替换成两个等号(==)。

  难点:由于是根据等号(=)的索引来进行对应判断和查找,所以在进行判断的时候,需要考虑很多种格式问题,比如:

  • 一个等号(=)的时候,左右有没有空格,或者是多个空格的情况,
  • 如果where直接是两个等号(==)的时候,我们就忽略无需对它进行转换。

解决方案

  根据上述的思路分析,我们直接上代码。

方案一

📌普通版

  我们先根据需求,将大致的实现代码写出来,最后再去考虑多种情况出现的问题。

package com.example.business.util;

import java.util.ArrayList;

/**
 * @ClassName: Test
 * @Description: 临时测试类
 * @Author yang
 * @Date 2022/12/20
 * @Version 1.0
 */
public class Test {


    public static void main(String[] args) {
        String WHERE = "app_id='005' AND keyid='0101'";
//        String WHERE = "app_id=005 AND keyid=0101";
//        String WHERE = "app_id= 005 AND keyid = 0101";
//        String WHERE = "app_id=005";

        if (WHERE.contains("\'")) {
			//去除字符串多余空格,只能存在一个空格(即把两个以上的空格替换成一个)
            ArrayList<Integer> indexList = new ArrayList<>();
            String strChars = WHERE.replaceAll(" {2,}", " ");
            char[] chars = strChars.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] == '=') {
                    indexList.add(i);
                }
            }
            for (Integer integer : indexList) {
                StringBuilder builder = new StringBuilder();
                int index = integer;
                boolean appendFlag = false;
                if (chars[index - 1] != '>' && chars[index - 1] != '<' && chars[index - 1] != '!') {
                    if (chars[index + 1] == '=') {//如:String WHERE = "pay_time == '2019/10/22'";
                        System.out.println("原句返回:" + WHERE);
                        return;
                    }
                    if (chars[index + 1] == ' ' && chars[index + 2] == '=') {//如:String WHERE = "pay_time =   ='2019/10/22'";或String WHERE = "pay_time =   = '2019/10/22'";
                        System.out.println("22222222:");
                        dealTwoEqual(WHERE);
                        return;
                    }
                    boolean flag = chars[index + 1] == ' ' || (chars[index + 1] == '\'' && chars[index + 1] != '=');//如:String WHERE = "pay_time = '2019/10/22'";或String WHERE = "pay_time =   '2019/10/22'";
                    while ((index + 1 < chars.length) && flag) {
                        flag = chars[index + 1] == ' ' || (chars[index + 1] == '\'' && chars[index + 1] != '=');
                        if (flag) {
                            appendFlag = true;
                            index++;
                        }
                    }


                }
                if (appendFlag) {
                    int arrIndex = 0;
                    for (int i = 0; i < indexList.size(); i++) {
                        int value = indexList.get(i);
                        if (value == integer) {
                            arrIndex = i;
                        }
                    }

                    if (arrIndex == 0) {
                        builder.append(strChars, 0, integer);
                        builder.append("==");
                        builder.append(strChars, index, chars.length);
                    } else {
                        builder.append(strChars, 0, integer + 1);
                        builder.append("==");
                        builder.append(strChars, index + 1, chars.length + 1);
                    }
                    strChars = builder.toString();
                }
            }
            System.out.println("builder:" + strChars);
            String str = strChars;
            if (str.contains(" and ")) {
                str = str.replace(" and ", " && ");
            }

            if (str.contains(" AND ")) {
                str = str.replace(" AND ", " && ");
            }

            if (str.contains(" or ")) {
                str = str.replace(" or ", " || ");
            }

            if (str.contains(" OR ")) {
                str = str.replace(" OR ", " || ");
            }
            System.out.println("str:" + str);
        } else {
            //去除字符串多余空格,只能存在一个空格(即把两个以上的空格替换成一个)
            ArrayList<Integer> indexList = new ArrayList<>();
            String strChars = WHERE.replaceAll(" {2,}", " ");
            char[] chars = strChars.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] == '=') {
                    indexList.add(i);
                }
            }
            for (Integer integer : indexList) {
                StringBuilder builder = new StringBuilder();
                int index = integer;
                boolean appendFlag = false;
                if (chars[index - 1] != '>' && chars[index - 1] != '<' && chars[index - 1] != '!') {
                    if (chars[index + 1] == '=') {
                        System.out.println("原句返回:" + WHERE);
                        return;
                    }
                    if (chars[index + 1] == ' ' && chars[index + 2] == '=') {
                        System.out.println("22222222:");
                        dealTwoEqual(WHERE);
                        return;
                    }
                    boolean flag = (chars[index] == '=' && chars[index + 1] == ' ') || (chars[index] == '=' && chars[index + 1] != ' ') || (chars[index] == '=' && chars[index + 1] != '\'' && chars[index + 1] != '=');
                    while ((index + 1 < chars.length) && flag) {
                        flag = (chars[index] == '=' && chars[index + 1] == ' ') || (chars[index] == '=' && chars[index + 1] != ' ') || (chars[index] == '=' && chars[index + 1] != '\'' && chars[index + 1] != '=');
                        if (flag) {
                            appendFlag = true;
                            index++;
                        }
                    }


                }
                if (appendFlag) {
                    int arrIndex = 0;
                    for (int i = 0; i < indexList.size(); i++) {
                        int value = indexList.get(i);
                        if (value == integer) {
                            arrIndex = i;
                        }
                    }

                    if (arrIndex == 0) {
                        builder.append(strChars, 0, integer);
                        builder.append("==");
                        builder.append(strChars, index, chars.length);
                    } else {
                        builder.append(strChars, 0, integer + 1);
                        builder.append("==");
                        builder.append(strChars, index + 1, chars.length + 1);
                    }
                    strChars = builder.toString();
                }
            }
            String str = strChars;
            if (str.contains(" and ")) {
                str = str.replace(" and ", " && ");
            }

            if (str.contains(" AND ")) {
                str = str.replace(" AND ", " && ");
            }

            if (str.contains(" or ")) {
                str = str.replace(" or ", " || ");
            }

            if (str.contains(" OR ")) {
                str = str.replace(" OR ", " || ");
            }
            System.out.println("str:" + str);
        }


    }


    public static void dealOneEqual(String where) {
        ArrayList<Integer> indexList = new ArrayList<>();
        String strChars = where.replaceAll(" {2,}", " ");
        char[] chars = strChars.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '=') {
                indexList.add(i);
            }
        }

        StringBuilder builder = new StringBuilder();
        for (Integer integer : indexList) {
            int index = integer;
            boolean appendFlag = false;
            if (chars[index - 1] != '>' && chars[index - 1] != '<' && chars[index - 1] != '!') {
                appendFlag = true;
                boolean flag = chars[index + 1] == ' ';
                while ((index + 1 < chars.length) && flag) {
                    flag = chars[index + 1] == ' ';
                    if (flag) {
                        index++;
                    }
                }
            }
            if (appendFlag) {
                builder.append(strChars, 0, integer);
                builder.append("==");
                builder.append(strChars, index + 1, chars.length);
            }
        }
        System.out.println("一个等号:" + builder);
    }


    public static void dealTwoEqual(String where) {
        ArrayList<Integer> indexList = new ArrayList<>();
        String strChars = where.replaceAll(" {2,}", " ");
        char[] chars = strChars.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '=') {
                indexList.add(i);
            }
        }

        StringBuilder builder = new StringBuilder();
        for (Integer integer : indexList) {
            int index = integer;
            boolean appendFlag = false;
            boolean flag = chars[index + 1] == ' ' && chars[index + 2] == '=';
            while ((index + 2 < chars.length) && flag) {
                flag = chars[index + 1] == ' ' && chars[index + 2] == '=';
                if (flag) {
                    appendFlag = true;
                    index++;
                }
            }
            if (appendFlag) {
                builder.append(strChars, 0, integer);
                builder.append("==");
                builder.append(strChars, index + 2, chars.length);
            }
        }
        System.out.println("两个等号:" + builder);
    }

}

输出结果
builder:app_id==‘005’ AND keyid==‘0101’
str:app_id==‘005’ && keyid==‘0101’

  经过多重测试后,发现此方案行不通,有些条件还是无法满足,比较条件超过两个,如下:

String WHERE = "app_id='005' AND keyid='0101' AND keyid='0101'";

输出结果
builder:app_id==‘005’ AND keyid==‘0101’ AND keyi==='0101
str:app_id==‘005’ && keyid==‘0101’ && keyi==='0101

  第三个就会引起索引替换问题出错,变成三个等号了,没办法,只能重新修改逻辑,继续改善。

★不推荐★


方案二

📌进阶版

  针对方案一不能满足多个条件替换的问题,我们对替换拼接的索引改成了动态的,先看代码:

package com.example.business.util;

import java.util.ArrayList;

/**
 * @ClassName: Test
 * @Description: 临时测试类
 * @Author yang
 * @Date 2022/12/20
 * @Version 1.0
 */
public class Test2 {


    public static void main(String[] args) {
//        String WHERE = "app_id='005' AND keyid='0101' AND keyid='0101'";//√
//        String WHERE = "app_id >= '005' AND keyid ='0101' AND keyid ='0101' AND keyid ='0101'";//X
//        String WHERE = "keyid ='0101' AND app_id >= '005' AND keyid ='0101' AND keyid ='0101'";//X
//        String WHERE = "keyid ='0101' AND app_id >= '005' AND app_id <= '005' AND keyid ='0101'";//X
//        String WHERE = "app_id >= '005' AND keyid ='0101'";//√
//        String WHERE = "keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "keyid ='0101' AND keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "pay_time >=2019/10/21 and pay_time <= 2019/10/22 and app_id = 001";//X
//        String WHERE = "pay_time >='2019/10/21' and pay_time <= '2019/10/22' and app_id = '001'";//X
//        String WHERE = "app_id=005 AND keyid=0101";//√
//        String WHERE = "app_id= 005 AND keyid = 0101";//√
        String WHERE = "app_id= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//√
//        String WHERE = "app_id>= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND app_id <=  005 AND keyid =   0101 AND keyid = 0105";//X
//        String WHERE = "keyid =    0101 AND keyid =    0105";//√
//        String WHERE = "app_id=005";//√
//        String WHERE = "app_id!=005";


        if (WHERE.contains("\'")) {
            //去除字符串多余空格,只能存在一个空格(即把两个以上的空格替换成一个)
            ArrayList<Integer> indexList = new ArrayList<>();
            String strChars = WHERE.replaceAll(" {2,}", " ");
            if (strChars.contains("> =") || strChars.contains("< =") || strChars.contains("! =") || strChars.contains("= =") || strChars.contains("==")) {
                System.out.println("sql语句格式错误,注意比较符(>=、<=、!=)中间不允许出现空格,不能出现两个等号(==)");
                return;
            }
            char[] chars = strChars.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] == '=') {
                    indexList.add(i);
                }
            }
            boolean sign = false;
            boolean num = false;
            for (Integer integer : indexList) {
                StringBuilder builder = new StringBuilder();
                int index = integer;
                boolean appendFlag = false;
                if (chars[index - 1] != '>' && chars[index - 1] != '<' && chars[index - 1] != '!') {
                    boolean flag = chars[index] == '=';
                    while ((index + 1 < chars.length) && flag) {
                        flag = chars[index] == '=';
                        if (flag) {
                            appendFlag = true;
                            index++;
                        }
                    }
                } else {
                    sign = true;
                }
//                if (sign) {
//                    builder.append(strChars, 0, integer);
                    builder.append("==");
//                    builder.append(strChars, index, chars.length);
//                    strChars = builder.toString();
//                }
                if (appendFlag) {
                    int arrIndex = 0;
                    for (int i = 0; i < indexList.size(); i++) {
                        int value = indexList.get(i);
                        if (value == integer) {
                            arrIndex = i;
                        }
                    }
                    int sum = 0;
                    char[] chars2 = strChars.toCharArray();
                    if (arrIndex == 0) {
                        builder.append(strChars, 0, integer);
                        builder.append("==");
                        builder.append(strChars, index, chars.length);
                    } else if (arrIndex > 0 && sign) {
                        builder.append(strChars, 0, integer);
                        builder.append("==");
                        builder.append(strChars, index, chars.length);
                        sign = false;
                        num = true;
                    } else if (arrIndex > 0 && !sign && num) {
                        builder.append(strChars, 0, integer + 1);
                        builder.append("==");
                        builder.append(strChars, index + 1, chars.length + 1);
                        num = false;
                    } else {
                        builder.append(strChars, 0, integer + arrIndex);
                        builder.append("==");
                        builder.append(strChars, index + arrIndex, chars.length + arrIndex);
                    }
                    strChars = builder.toString();
                }
            }
//            System.out.println("builder:" + strChars);
            String str = strChars.toLowerCase();
            if (str.contains(" and ")) {
                str = str.replace(" and ", " && ");
            }
            if (str.contains(" or ")) {
                str = str.replace(" or ", " || ");
            }
            System.out.println("str:" + str);
        } else {
            //去除字符串多余空格,只能存在一个空格(即把两个以上的空格替换成一个)
            ArrayList<Integer> indexList = new ArrayList<>();
            String strChars = WHERE.replaceAll(" {2,}", " ");
            if (strChars.contains("> =") || strChars.contains("< =") || strChars.contains("! =") || strChars.contains("= =") || strChars.contains("==")) {
                System.out.println("sql语句格式错误,注意比较符(>=、<=、!=)中间不允许出现空格,不能出现两个等号(==)");
                return;
            }
            char[] chars = strChars.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                if (chars[i] == '=') {
                    indexList.add(i);
                }
            }
            for (Integer integer : indexList) {
                StringBuilder builder = new StringBuilder();
                int index = integer;
                boolean appendFlag = false;
                if (chars[index - 1] != '>' && chars[index - 1] != '<' && chars[index - 1] != '!') {
                    boolean flag = chars[index] == '=';
                    while ((index + 1 < chars.length) && flag) {
                        flag = chars[index] == '=';
                        if (flag) {
                            appendFlag = true;
                            index++;
                        }
                    }
                }
                if (appendFlag) {
                    int arrIndex = 0;
                    for (int i = 0; i < indexList.size(); i++) {
                        int value = indexList.get(i);
                        if (value == integer) {
                            arrIndex = i;
                        }
                    }
                    char[] chars2 = strChars.toCharArray();
                    if (arrIndex == 0) {
                        builder.append(strChars, 0, integer);
                        builder.append("==");
                        builder.append(strChars, index, chars.length);
                    } else {
                        builder.append(strChars, 0, integer + arrIndex);
                        builder.append("==");
                        builder.append(strChars, index + arrIndex, chars.length + arrIndex);
                    }
                    strChars = builder.toString();
                }
            }
            String str = strChars.toLowerCase();
            if (str.contains(" and ")) {
                str = str.replace(" and ", " && ");
            }
            if (str.contains(" or ")) {
                str = str.replace(" or ", " || ");
            }
            System.out.println("str:" + str);
        }
    }    

}

先看结果:

输出结果
str:app_id== 005 && keyid == 0101 && keyid == 0101 && keyid == 0101 && keyid == 0101 && keyid == 0101 && keyid == 0101 && keyid == 0101

  发现可以解决方案一的问题。可是,随着慢慢的测试,bug还是出现了。比如条件中不是单纯的等号,而是包含大于等于、小于等于(>=、<=)等等情况,就会抛索引越界异常。如下:

String WHERE = "app_id >= '005' AND keyid ='0101' AND keyid ='0101' AND keyid ='0101'";

输出结果
Exception in thread “main” java.lang.IndexOutOfBoundsException: start 66, end 72, s.length() 71
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:539)
at java.lang.StringBuilder.append(StringBuilder.java:175)
at com.example.business.util.Test2.main(Test2.java:102)

  经过多重的调试,发现根据这个where语句的判断是存在很多问题,很多种时候,空格也是导致判断条件出现漏判,是行不通的,很多种多重条件,无法同时兼容,最后参考sql的语法,决定对目标where进行一下限定判断,即(比较符(>=、<=、!=、<>)中间不允许出现空格,不能出现两个等号(==或= =))

  如果是这样,那逻辑就会容易很多了,我们可以忽略比较符(>=、<=、!=、<>)中间出现空格的问题,以及两个等号(==或= =))的问题,这样,我们可以直接根据等号(=)进行分割,对分割后的数组进行判断拼接。详细代码请看方案三。

★不推荐★


方案三

📌终极版

  总结了方案一和方案二出现的各种问题,对原先的代码进行了重构,先看代码:

package com.example.business.util;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName: Test
 * @Description: 临时测试类
 * @Author yang
 * @Date 2022/12/20
 * @Version 1.0
 */
public class Test3 {


    public static void main(String[] args) {
//        String WHERE = "app_id='005' AND keyid='0101' AND keyid='0101'";//√
//        String WHERE = "app_id >= '005' AND keyid ='0101' AND keyid ='0101' AND keyid ='0101'";//
//        String WHERE = "keyid ='0101' AND app_id <> '005' AND keyid <>'0101' AND keyid ='0101'";//X
        String WHERE = "keyid ='0101' AND app_id >= '005' AND app_id <= '005' AND keyid ='0101'";//X
//        String WHERE = "app_id >= '005' AND keyid ='0101'";//√
//        String WHERE = "keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "keyid ='0101' AND keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "pay_time >=2019/10/21 and pay_time <= 2019/10/22 and app_id = 001";//X
//        String WHERE = "pay_time >='2019/10/21' and pay_time <= '2019/10/22' and app_id = '001'";//X
//        String WHERE = "app_id=005 AND keyid=0101";//√
//        String WHERE = "app_id= 005 AND keyid = 0101";//√
//        String WHERE = "app_id= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//√
//        String WHERE = "app_id>= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND app_id <=  005 AND keyid = 0101 AND keyid = 0105";//X
//        String WHERE = "keyid =    0101 AND keyid =    0105";//√
//        String WHERE = "app_id=005";//√
//        String WHERE = "app_id!=005";
//        String WHERE = "app_id< >005";
//        String WHERE = "app_id< =005";
//        String WHERE = "app_id> =005";
//        String WHERE = "app_id>005";
//        String WHERE = "app_id>=005 and app_id BETWEEN '2018-06-28' AND '2018-09-28'";
//        String WHERE = "app_id like '2018-09-28'";
//        String WHERE = "app_id in (1,2) and a=8";
//        String WHERE = "app_id in (1,2) and a>=8";
//        String WHERE = "app_id<005 and appid=005 or key=50 and a>=10 or b<=50 and c!=6";
//        String WHERE = "app_id BETWEEN '2018-06-28' AND '2018-09-28' and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
//        String WHERE = "app_id like '2018-09-28' and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
//        String WHERE = "app_id in (1,2) and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
        WHERE = WHERE.toLowerCase();
        String strChars = WHERE.replaceAll(" {2,}", " ");
        if (strChars.contains("> =") || strChars.contains("< =") || strChars.contains("! =") || strChars.contains("< >") || strChars.contains("= =") || strChars.contains("==")) {
            System.out.println("sql语句格式错误,注意比较符(>=、<=、!=、<>)中间不允许出现空格,不能出现两个等号(==或= =)");
            return;
        }
        String[] arr = strChars.split("=");
        System.out.println(Arrays.toString(arr));
        StringBuilder str = new StringBuilder();

        for (int i = 0; i < arr.length; i++) {
            String a = arr[i];
            if (!a.contains("<") && !a.contains(">") && !a.contains("!") && !(i == arr.length - 1)) {
                str.append(a + "==");
            } else if (i == arr.length - 1) {
                str.append(a);
            } else if (a.contains("<>")) {
                str.append(a + "==");
            } else {
                 str.append(a + "=");
            }
        }
        String strWhere = str.toString().replace("<>", "!=");
        System.out.println(strWhere);

        if (strWhere.contains(" and ")) {
            strWhere = strWhere.replace(" and ", " && ");
        }
        if (strWhere.contains(" or ")) {
            strWhere = strWhere.replace(" or ", " || ");
        }

        System.out.println(strWhere);     
    }
}

输出结果
[keyid , ‘0101’ and app_id >, ‘005’ and app_id <, ‘005’ and keyid , ‘0101’]
keyid ==‘0101’ and app_id >= ‘005’ and app_id <= ‘005’ and keyid ==‘0101’
keyid ==‘0101’ && app_id >= ‘005’ && app_id <= ‘005’ && keyid ==‘0101’

  原本以为方案三已经完成所有需求,结果经过多种运算符的测试时,还是发现有个bug,就是只有一个大于号或者小于号(< 、>)时,拼接会有问题,如下:

String WHERE = "app_id<005 and appid=005 or key=50 and a>=10 or b<=50 and c!=6";

输出结果
[app_id<005 and appid, 005 or key, 50 and a>, 10 or b<, 50 and c!, 6]
app_id<005 and appid=005 or key50 and a>=10 or b<=50 and c!=6
app_id<005 && appid=005 || key
50 && a>=10 || b<=50 && c!=6

  经过Debug调试发现,只有一个只有一个大于号或者小于号(< 、>)时,直接走的是else的判断,就拼了一个等号(=),明显是不符合要求的,那么怎么去实现这个bug吗?经过细心观察,发现了一个特点,就是以等号(=)分割后,每段字符后面如果不是特殊字符,即不是大于号、小于号和叹号(< 、>、!)时,是需要拼接两个等号(==)的,这样才符合前面的需求。所以,对else部分的代码又进行了一层代码,详情请往下看。

★不推荐★


方案四

📌标准版

  针对方案三出现的bug,排查发现,是漏掉了一个判断限定条件,即分割后的每段字符串,我们应该检验一下它的最后一个字符,是不是特殊字符(即是否包含 <、>、 !)。

package com.example.business.util;

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName: Test
 * @Description: 临时测试类
 * @Author yang
 * @Date 2022/12/20
 * @Version 1.0
 */
public class Test3 {


    public static void main(String[] args) {
//        String WHERE = "app_id='005' AND keyid='0101' AND keyid='0101'";//√
//        String WHERE = "app_id >= '005' AND keyid ='0101' AND keyid ='0101' AND keyid ='0101'";//
//        String WHERE = "keyid ='0101' AND app_id <> '005' AND keyid <>'0101' AND keyid ='0101'";//X
//        String WHERE = "keyid ='0101' AND app_id >= '005' AND app_id <= '005' AND keyid ='0101'";//X
//        String WHERE = "app_id >= '005' AND keyid ='0101'";//√
//        String WHERE = "keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "keyid ='0101' AND keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "pay_time >=2019/10/21 and pay_time <= 2019/10/22 and app_id = 001";//X
//        String WHERE = "pay_time >='2019/10/21' and pay_time <= '2019/10/22' and app_id = '001'";//X
//        String WHERE = "app_id=005 AND keyid=0101";//√
//        String WHERE = "app_id= 005 AND keyid = 0101";//√
//        String WHERE = "app_id= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//√
//        String WHERE = "app_id>= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND app_id <=  005 AND keyid = 0101 AND keyid = 0105";//X
//        String WHERE = "keyid =    0101 AND keyid =    0105";//√
//        String WHERE = "app_id=005";//√
//        String WHERE = "app_id!=005";
//        String WHERE = "app_id< >005";
//        String WHERE = "app_id< =005";
//        String WHERE = "app_id> =005";
//        String WHERE = "app_id>005";
//        String WHERE = "app_id>=005 and app_id BETWEEN '2018-06-28' AND '2018-09-28'";
//        String WHERE = "app_id like '2018-09-28'";
//        String WHERE = "app_id in (1,2) and a=8";
//        String WHERE = "app_id in (1,2) and a>=8";
        String WHERE = "app_id<005 and appid=005 or key=50 and a>=10 or b<=50 and c!=6";
//        String WHERE = "app_id BETWEEN '2018-06-28' AND '2018-09-28' and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
//        String WHERE = "app_id like '2018-09-28' and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
//        String WHERE = "app_id in (1,2) and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
        WHERE = WHERE.toLowerCase();
        String strChars = WHERE.replaceAll(" {2,}", " ");
        if (strChars.contains("> =") || strChars.contains("< =") || strChars.contains("! =") || strChars.contains("< >") || strChars.contains("= =") || strChars.contains("==")) {
            System.out.println("sql语句格式错误,注意比较符(>=、<=、!=、<>)中间不允许出现空格,不能出现两个等号(==或= =)");
            return;
        }
        String[] arr = strChars.split("=");
        System.out.println(Arrays.toString(arr));
        StringBuilder str = new StringBuilder();

        for (int i = 0; i < arr.length; i++) {
            String a = arr[i];
            if (!a.contains("<") && !a.contains(">") && !a.contains("!") && !(i == arr.length - 1)) {
                str.append(a + "==");
            } else if (i == arr.length - 1) {
                str.append(a);
            } else if (a.contains("<>")) {
                str.append(a + "==");
            } else {
                String last = a.substring(a.length() - 1);
                if (!(isSpecialChar(last))) {
                    str.append(a + "==");
                } else {
                    str.append(a + "=");
                }
            }
        }
        String strWhere = str.toString().replace("<>", "!=");
        System.out.println(strWhere);

        if (strWhere.contains(" and ")) {
            strWhere = strWhere.replace(" and ", " && ");
        }
        if (strWhere.contains(" or ")) {
            strWhere = strWhere.replace(" or ", " || ");
        }

        System.out.println(strWhere);
    }


    public static boolean isSpecialChar(String str) {
        String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]|\n|\r|\t";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.find();
    }
}

输出结果
[app_id<005 and appid, 005 or key, 50 and a>, 10 or b<, 50 and c!, 6]
app_id<005 and appid005 or key50 and a>=10 or b<=50 and c!=6
app_id<005 && appid005 || key50 && a>=10 || b<=50 && c!=6

  经过了上面的多种条件测试,我能想到的sql语法的都测试了,暂时没有发现问题。

★推荐★


附 JexlEngine 方法

/**
 * 这个方法能够将字符串当作java代码来执行
 *
 * @param express
 * @return
 */
public static Object executeString(String express, Map<String, Object> parameter) {
    JexlEngine jexlEngine = new JexlEngine();

    Expression expression;
    try {
        expression = jexlEngine.createExpression(express);//将参数中的字符串传进来
    } catch (Exception e) {
        throw new JexlException(null, "Jexl异常");
    }

    JexlContext jexlContext = new MapContext();
    for (String key : parameter.keySet()) {//遍历传过来的参数
        jexlContext.set(key, parameter.get(key));//将传进来的参数替换到表达式中去
    }
    if (null == expression.evaluate(jexlContext)) {//执行表达式
        return "";//为空就返回空字符串
    }
    return expression.evaluate(jexlContext);//执行表达式,返回结果
}

完整测试源码:

package com.example.business.util;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName: Test
 * @Description: 临时测试类
 * @Author yang
 * @Date 2022/12/20
 * @Version 1.0
 */
public class Test3 {


    public static void main(String[] args) {
//        String WHERE = "app_id='005' AND keyid='0101' AND keyid='0101'";//√
//        String WHERE = "app_id >= '005' AND keyid ='0101' AND keyid ='0101' AND keyid ='0101'";//
//        String WHERE = "keyid ='0101' AND app_id <> '005' AND keyid <>'0101' AND keyid ='0101'";//X
//        String WHERE = "keyid ='0101' AND app_id >= '005' AND app_id <= '005' AND keyid ='0101'";//X
//        String WHERE = "app_id >= '005' AND keyid ='0101'";//√
//        String WHERE = "keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "keyid ='0101' AND keyid ='0101' AND app_id >= '005'";//√
//        String WHERE = "pay_time >=2019/10/21 and pay_time <= 2019/10/22 and app_id = 001";//X
//        String WHERE = "pay_time >='2019/10/21' and pay_time <= '2019/10/22' and app_id = '001'";//X
//        String WHERE = "app_id=005 AND keyid=0101";//√
//        String WHERE = "app_id= 005 AND keyid = 0101";//√
//        String WHERE = "app_id= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//√
//        String WHERE = "app_id>= 005 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND keyid = 0101";//X
//        String WHERE = "app_id >=  005 AND app_id <=  005 AND keyid = 0101 AND keyid = 0105";//X
//        String WHERE = "keyid =    0101 AND keyid =    0105";//√
//        String WHERE = "app_id=005";//√
//        String WHERE = "app_id!=005";
//        String WHERE = "app_id< >005";
//        String WHERE = "app_id< =005";
//        String WHERE = "app_id> =005";
//        String WHERE = "app_id>005";
//        String WHERE = "app_id>=005 and app_id BETWEEN '2018-06-28' AND '2018-09-28'";
//        String WHERE = "app_id like '2018-09-28'";
//        String WHERE = "app_id in (1,2) and a=8";
//        String WHERE = "app_id in (1,2) and a>=8";
        String WHERE = "app_id<005 and appid=005 or key=50 and a>=10 or b<=50 and c!=6";
//        String WHERE = "app_id BETWEEN '2018-06-28' AND '2018-09-28' and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
//        String WHERE = "app_id like '2018-09-28' and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
//        String WHERE = "app_id in (1,2) and appid=005 or key=50 and a>=10 or b<=50 and c!=6;";
        WHERE = WHERE.toLowerCase();
        String strChars = WHERE.replaceAll(" {2,}", " ");
        if (strChars.contains("> =") || strChars.contains("< =") || strChars.contains("! =") || strChars.contains("< >") || strChars.contains("= =") || strChars.contains("==")) {
            System.out.println("sql语句格式错误,注意比较符(>=、<=、!=、<>)中间不允许出现空格,不能出现两个等号(==或= =)");
            return;
        }
        String[] arr = strChars.split("=");
        System.out.println(Arrays.toString(arr));
        StringBuilder str = new StringBuilder();

        for (int i = 0; i < arr.length; i++) {
            String a = arr[i];
            if (!a.contains("<") && !a.contains(">") && !a.contains("!") && !(i == arr.length - 1)) {
                str.append(a + "==");
            } else if (i == arr.length - 1) {
                str.append(a);
            } else if (a.contains("<>")) {
                str.append(a + "==");
            } else {
                String last = a.substring(a.length() - 1);
                if (!(isSpecialChar(last))) {
                    str.append(a + "==");
                } else {
                    str.append(a + "=");
                }
            }
        }
        String strWhere = str.toString().replace("<>", "!=");
        System.out.println(strWhere);

        if (strWhere.contains(" and ")) {
            strWhere = strWhere.replace(" and ", " && ");
        }
        if (strWhere.contains(" or ")) {
            strWhere = strWhere.replace(" or ", " || ");
        }

        System.out.println(strWhere);
        // 测试功能
        Map<String, Object> map = new HashMap<>();
        map.put("keyid", "0101");
        map.put("app_id", "006");
        Object o = StringVerifyUtil.executeString("keyid =='0101' and  app_id != '005'", map);
        System.out.println(o);
    }


    public static boolean isSpecialChar(String str) {
        String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]|\n|\r|\t";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.find();
    }
}

输出结果
[app_id<005 and appid, 005 or key, 50 and a>, 10 or b<, 50 and c!, 6]
app_id<005 and appid005 or key50 and a>=10 or b<=50 and c!=6
app_id<005 && appid005 || key50 && a>=10 || b<=50 && c!=6
true


结语

  这种处理where语句的,涉及到的各种写法实在是太多了,光是前面写逻辑都写了不少于10个版本,种种问题都是警告种种测试才发现,很难一步到位写好整个逻辑判断。(在此说明:此种做法是根据某些场景的特殊需求,迫不得已才去做。实际中应该没有几个人会有这样的需求。)原来以为在Java中能找到合适的数据库对象类处理,奈何没有找到(如果有知道的,欢迎评论区不吝指教)。

  归根结底就是使用JexlEngine这个类(能将字符转成Java代码运行),它不认sql的一个等号(=),必须是两个等号(==)才行,而且AND连接语句也不能是大写,要小写and,这里建议转(&&),or 转(||)。文章来源地址https://www.toymoban.com/news/detail-782342.html

jexlengine,练习code,Java,java,mysql,数据结构
创作不易,感谢您的点赞与支持。

到了这里,关于解决JexlEngine执行where条件时,等号(=)替换成双等号(==)问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 简明SQL条件查询指南:掌握WHERE实现数据筛选

    条件查询是用于从数据库中根据特定条件筛选数据行的一种方式,它避免了检索整个表中的数据。通常,使用 WHERE 子句来定义过滤条件,只有符合这些条件的数据行才会被返回。 SQL中的运算符有:=、!=、、 等,用于进行条件判断。 在逻辑运算中,常见的运算符包括: and:

    2024年02月09日
    浏览(67)
  • MySQL数据库——MySQL WHERE:条件查询数据

    在 MySQL 中,如果需要有条件的从数据表中查询数据,可以使用 WHERE 来指定查询条件。 使用 WHERE 的语法格式如下: WHERE 查询条件 查询条件可以是: 带比较运算符和逻辑运算符的查询条件 带 BETWEEN AND 的查询条件 带 IS NULL 的查询条件 带 IN

    2024年02月03日
    浏览(58)
  • ORM 自定义sql,where条件变量值为null,转为:where remark=null是不对的

    ORM 自定义sql,where条件变量值为null,转为:where remark=null是不对的 该如何解决呢? 例子如下: 需要在变量的值为null时,改为: remark is null 这是SQL的语法. 使用ORM自定义sql, 在where条件,使用remark=#{remark @toIsNULL1}才是对的. 代码参考: https://gitee.com/automvc/bee-exam Bee,一个简单易用,功能强大的

    2024年02月12日
    浏览(55)
  • SQL 语句中 where 条件后 写上1=1 是什么意思

    程序员在编程过程中,经常会在代码中使用到“where 1=1”,这是为什么呢? SQL注入 初次看到这种写法的同学肯定很纳闷,加不加where 1=1,查询不都一样吗?例如: 查询出来的结果完全没有区别呀。 是的,上面的查询结果是没有区别,但是这并不是我们要添加它的目的。我们

    2024年01月21日
    浏览(36)
  • MySql按条件插入数据,MySQL插入语句写where条件,MySQL在插入时做幂等

    使用MySQL的删、改、查功能时,我们都可以根据where条件来对指定数据进行操作。 插入语句如何通过where条件,来判断是否允许插入呢? 此时表里有三条数据了: 上面sql执行结果: insert into test_table (id, content) select * from (select ‘4’, ‘内容4’) as tmp where not exists ( select 1 from

    2023年04月09日
    浏览(47)
  • 解决Unknown column ‘xxx‘ in ‘where clause‘问题!!(泪的教训!!)

    本人做SSM项目的时候,在做删除功能时,发现找不到字段,在搜索了各种博客之后终于找到了解决办法 遇到上面报错的时候一定是属性和字段不对应的问题!!要么找不到属性,要么找不到数据库的字段!! 通过一系列的操作试错,我发现不是找不到属性的原因(因为都试

    2023年04月08日
    浏览(42)
  • Thinkphp6 的 where 查询条件 and 和 or 的 操作

    tp3.2 来说 or 或者and 的操作可以在一个数组中用_logic 来解决 $where = [\\\'id\\\'=1,\\\'name\\\'=\\\'小表\\\',\\\'_logic\\\'=\\\'or\\\']     但是tp6的不行。 $where1 = [\\\'id\\\'=1, \\\'name\\\'=\\\'小白\\\']; $where2 = [\\\'id\\\'=2, \\\'name\\\'=\\\'小黑\\\']; $where = [$where1, $where2,\\\'_logic\\\'=\\\'or\\\'] tp6的and 和 or 可以实现的方法比较多 已知:-where(A)-where(B) 俩个条件关

    2024年02月06日
    浏览(53)
  • MySQL中使用IF子查询实现条件判断(where之后用if)

    废话不多说,直接上代码

    2023年04月23日
    浏览(62)
  • SQL sever数据库----基础增删改查操作与where条件限制

    在SQL sever中使用where语句,可以对各种操作添加限制条件 基础格式为 ———————— where 逻辑表达式 例如限制条件的查询 select 范围 from 表名 where 逻辑表达式 逻辑表达式就是一个判断 如 a 5 、a+69、a5 and b5 各种符号及作用如下面的表所示 比较运算符 符号 含义 大于 小于

    2023年04月18日
    浏览(47)
  • 北京地区MySQL培训课程:深度解析查询语句中的WHERE条件设置

    MySQL如果在查询时想要获取满足的条件的记录,就需要使用WHERE子句,WHERE子句用于在 MySQL 中过滤查询结果,只返回满足条件的数据记录。 语法格式: SELECT column1, column2, ...FROM table_name WHERE condition; SELECT 列名, ...FROM 那个表 WHERE 条件; 下图为示例表格 示例1:查询等级是“A”的

    2024年02月19日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包