如何将String类型的字符串当成Java代码执行

写在前面

设想一个这样的问题:如果前端通过拼接生成了一个判断语句: age > 0,
那么传递到后端,肯定是用String类型来存储:

String test = "age > 0";

那么我想执行前端传递过来的判断条件该怎么办呢?

表达式语言引擎:Apache Commons JEXL

这里展示了一个工具类

import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;


import java.util.Map;

/**
 * 这个工具类是为了能够把字符串当作java代码来执行
 */
public class ExecuteStringAsCodeUtils {
    /**
     * 这个方法能够将字符串当作java代码来执行
     * @param express
     * @return
     */
    public Object executeString(String express, Map<String,Object> parameter) {
        JexlEngine jexlEngine = new JexlEngine();
        Expression expression = jexlEngine.createExpression(express);//将参数中的字符串传进来
        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);//执行表达式,返回结果
    }


}

调用方式:

//创建工具类
ExecuteStringAsCodeUtils tool = new ExecuteStringAsCodeUtils();
String condition = "age > 0";
int age = 1;
Map<String,Object> map=new HashMap<String,Object>();
map.put("age",age);
boolean res = (boolean)tool.executeString(condition,map);
System.out.println(res);

提取字符串表达式的变量名

问题描述:
在字符串 "age > 3 || ‘zhangsan’.equals(name) "中,age,name是变量名,考虑将变量名提取出来
为什么有这个想法:
我们发现,如果HashMap中没有age或者name的变量名时,执行就会报错,因此设计一个方法,用来提取字符串表达式中包含的变量名
大致代码如下:

import java.util.*;

public class Test {
    public static void main(String[] args) {
        String exp = "(aa >= bb )|| (aa <= cc) ||(dd < ee) || (ff != gg) && (ff == ee) &&(!'Yes'.equals(STR))";
        parseKeysFromExpression(exp);
    }

    //获取表达式中的参数集合
    public static Set<String> parseKeysFromExpression(String args){
        Set<String> arg_set = new HashSet<>();
        //去掉args中多余的空格
        args = args.replaceAll(" ","");
        //第一道过滤,过滤表达式中的 &&
        String[] split1 = args.split("&&");
        //第二道过滤,过滤表达式中的 ||
        split1 = makeANewStrings(split1,"[||]");
        //第三道,过滤表达式中的比较运算符
        split1 = makeANewStrings(split1,"[!=><()]");
        //第四道,过滤字符串的等于
        split1 = makeANewStrings(split1,".equals");
        for(int i=0; i< split1.length; ++i){
        //排除掉空字符串,以及带单引号的字符串(这在表达式中是常量字符,而非变量)
            if(!"".equals(split1[i])&&!split1[i].contains("\'")) {
                arg_set.add(split1[i]);
                //System.out.println(split1[i]);
            }
        }
        //System.out.println("set:"+arg_set);
        return  arg_set;
    }

    //将字符数组中的每个字符分割后,组成一个新数组
    public static String[] makeANewStrings(String[] org,String exp){
        List<String> ans = new ArrayList<>();
        for(int i=0; i< org.length; ++i){//遍历字符串数组
            String[] split = org[i].split(exp);
            for (int j=0; j<split.length; ++j){
                ans.add(split[j]);
            }
        }
        String[] ans2 = new String[ans.size()];
        return  ans.toArray(ans2);
    }

}

你可能感兴趣的:(java,python,开发语言)