jexl2 报错 JexlException 的解决方法

今天,在做功能的时候,遇到一个问题。

xml文件中有配置限制条件,例如:

<CONDITION TYPE="range$in" 
PARASNAME="userlevel$department" 
EXPRESSION="(userlevel) and (department)">
	[0,4]$[开发部][测试部]
</CONDITION>

其中,PARASNAME 中配置的是变量名称; TYPE用来描述变量和值的关系;EXPRESSION 是各个变量的逻辑关系。

需要实现这样一个功能:

根据前台传入的变量值,以及EXPRESSION中配置的表达式的逻辑关系,计算出当前情况是否满足条件,然后返回一个结果。

初步想法是,把 EXPRESSION 中的内容按如下规则进行替换:
变量–>变量和值的关系
and -->&&

就像这样:

(userlevel>=0&&userlevel<=4)&&
([开发部][测试部].indexOf(department)>0)

但问题是,替换之后的表达式如何执行呢?


通过查询,还真有可以执行表达式的方法。一般通过jexl2 方式。

首先引入jar包:

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-jexl</artifactId>
	<version>2.0</version>
</dependency>

其次,写好执行表达式的函数:

/*
	exp:表达式字符串
	map:表达式中的变量和值
*/
public static Object exeExpression(String exp,Map<String,Object> map){  
        JexlEngine jexl=new JexlEngine();  
        Expression e = jexl.createExpression(exp);
        JexlContext jc = new MapContext();  
        for(String key:map.keySet()){//copy一下参数Map到JexlContext
            jc.set(key, map.get(key));  
        }  
        if(e.evaluate(jc)==null){  
            return "";  
        }  
        return e.evaluate(jc);  
	}  
}

调用方法:

Map<String,Object> map=new HashMap<String,Object>(); 
map.put("userlevel","1"); 
map.put("department","aaa");  
String expression=
"(userlevel>=0&&userlevel<=4)&&([开发部][测试部].indexOf(department)>0)"; 
Object code = convertToCode(expression,map);
System.out.println(""+code);

执行函数报错:

Exception in thread "main" org.apache.commons.jexl2.JexlException: com.test.TestReg.convertToCode@37tokenization failed
	at org.apache.commons.jexl2.JexlEngine.parse(JexlEngine.java:816)
	at org.apache.commons.jexl2.JexlEngine.createExpression(JexlEngine.java:380)
	at org.apache.commons.jexl2.JexlEngine.createExpression(JexlEngine.java:364)
	at com.test.TestReg.convertToCode(TestReg.java:37)
	at com.test.TestReg.main(TestReg.java:20)
Caused by: org.apache.commons.jexl2.parser.TokenMgrError: Lexical error at line 1, column 32.  Encountered: "\u5f00" (24320), after : ""
	at org.apache.commons.jexl2.parser.ParserTokenManager.getNextToken(ParserTokenManager.java:1564)

看提示的意思是有汉字,哦,忘记了给字符串加引号了。

又改成如下:

String expression="(userlevel>=0&&userlevel<=4)&&(\"[开发部][测试部]\".indexOf(department)>0)"; 

还是报同样的错误。

后来换了个思路,把这些常量放到放到变量Map里。

map.put("depart","[开发部][测试部]");  
String expression="(userlevel>=0&&userlevel<=4)&&(depart.indexOf(department)>0)"; 
			

输出结果:

false


问题解决,原来jexl2表达式不支持字符串常量。
通过研究 jexl2官网 发现:

1.构建参数值的Map可以优化一下,简化代码:
这里写图片描述

/*
	exp:表达式字符串
	map:表达式中的变量和值
*/
public static Object exeExpression(String exp,Map<String,Object> map){  
        JexlEngine jexl=new JexlEngine();  
        Expression e = jexl.createExpression(exp);
        JexlContext jc = new MapContext(map);  
        if(e.evaluate(jc)==null){  
            return "";  
        }  
        return e.evaluate(jc);  
	}  
}

2 创建JEXL engine时,最好用单例模式。(可能是3.0版本才支持)
这里写图片描述

 private static final JexlEngine jexl = 
 new JexlBuilder.cache(512).strict(true).silent(false).create();
        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷风在北京

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值