Code Monkey home page Code Monkey logo

qlexpress's Issues

有没有规则检查工具

你好,规则执行报错:
程序错误,不满足语法规范,没有匹配到合适的语法,最大匹配致[0:0]

报这种错感觉很难排查规则哪里写的不对。
各位在排查这种问题的方法是什么,有没有工具支持呢

宏定义设置macroName的问题

runner.addMacro方法参数‘macroName’如果前缀是数字的话,会调用Integer.parseInt转换,导致报NumberFormatException异常,比如:'50元立减券',就会出现上述问题。

我通过macro调用function,报找不到function

 ExpressRunner runner = new ExpressRunner(false, false);
          runner.addFunctionOfServiceMethod("changeBrand",new BrandService(),"changeBrand",new Class[] {DroolsRequest.class},null);
             runner.addMacro("changeBrandMacro","changeBrand11(droolsRequest)");
            DefaultContext<String, Object> context = new DefaultContext<>();
            context.put("PARAM1", 12);
            context.put("PARAM2", 60);
            context.put("droolsRequest",droolsRequest);
            expression = initial(runner, “changeBrandMacro and PARAM1 + PARAM2>60”);
            result = (Boolean) runner.execute(expression, context, errorInfo, true, false);

其中

public class BrandService {

    public boolean changeBrand(DroolsRequest droolsRequest){
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++");
        System.out.println(droolsRequest.asXML());
        return true;
    }
}

报错
java.lang.Exception: 在Runner的操作符定义和自定义函数中都没有找到"changeBrand"的定义
我看了下源码,macro中去调用function时候,查找的function是去symbolTable找的,但是addFunctionOfServiceMethod却是往functions里边添加的,请问是我什么地方写错了么?

区间表达式执行不支持

现在发现个问题,区间比较表达式,比如1<=a<=100,目前是不支持的,在执行的过程中会优先将1<=a得到的bool值和<=100做比较,这个时候就会抛出异常;

虽然使用1<=a && a<=100也可以兼容下,但是感觉这样还是不方便。请问下能否支持类似1<=a<=100这种表达式吗?

image

表达式计算不支持单字符类型比较

例如,如下测试:

@Test
public void testCharcharComapre() throws Exception {
	ExpressRunner runner = new ExpressRunner();
	String express = "'a'=='a' && '9.2'>='9.2' && '2018-05-09 17:47:31'>='2018-05-09 17:47:30'";
	Boolean r = (Boolean) runner.execute(express, null, null, true, false);
	assert r == true;
}

执行报以下错误:

java.lang.Exception: run QlExpress Exception at line 1 :

	at com.ql.util.express.instruction.detail.InstructionOperator.execute(InstructionOperator.java:48)
	at com.ql.util.express.InstructionSet.executeInnerOrigiInstruction(InstructionSet.java:204)
	at com.ql.util.express.InstructionSet.excute(InstructionSet.java:170)
	at com.ql.util.express.InstructionSetRunner.execute(InstructionSetRunner.java:59)
	at com.ql.util.express.InstructionSetRunner.execute(InstructionSetRunner.java:46)
	at com.ql.util.express.InstructionSetRunner.executeOuter(InstructionSetRunner.java:18)
	at com.ql.util.express.ExpressRunner.execute(ExpressRunner.java:570)
	at com.ql.util.express.ExpressRunner.execute(ExpressRunner.java:538)
	at com.ql.util.express.example.OperatorTest.testCharcharComapre(OperatorTest.java:93)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
	at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
	at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
	at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
	at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
	at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
	at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
	at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
	at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
	at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
	at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:130)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.Exception: aa不能执行compare 操作
	at com.ql.util.express.Operator.compareData(Operator.java:66)
	at com.ql.util.express.instruction.op.OperatorEqualsLessMore.executeInner(OperatorEqualsLessMore.java:50)
	at com.ql.util.express.instruction.op.OperatorEqualsLessMore.executeInner(OperatorEqualsLessMore.java:25)
	at com.ql.util.express.instruction.op.OperatorEqualsLessMore.executeInner(OperatorEqualsLessMore.java:21)
	at com.ql.util.express.Operator.executeInner(Operator.java:20)
	at com.ql.util.express.instruction.op.OperatorBase.execute(OperatorBase.java:67)
	at com.ql.util.express.instruction.detail.InstructionOperator.execute(InstructionOperator.java:44)
	... 29 more

不支持注释吗?

加了注释(//)报语法错误,去掉就OK了
是不支持还是我用法不正确?

Nested parenthesis not supported or a bug?

version : 3.2.0


for the following program:

runner.addOperatorWithAlias("如果", "if",null);
runner.addOperatorWithAlias("则", "then",null);
runner.addOperatorWithAlias("否则", "else",null);

exp = "如果  (如果 1==2 则 false 否则 true) 则 {2+2;} 否则 {20 + 20;}";
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
runner.execute(exp,nil,null,false,false,null);

image

step by step debuging, found that the following function does parse not well

private  static QLMatchResult findMatchStatementWithAddRoot(INodeTypeManager aManager,QLPatternNode pattern ,List<? extends IDataNode> nodes,int point,boolean isRoot,AtomicLong maxMatchPoint) throws Exception{
		QLMatchResult result = null;
		List<QLMatchResultTree> tempList = null;
		int count = 0;
		int lastPoint = point;
		while(true){
			QLMatchResult tempResult = null;
			if (pattern.matchMode == MatchMode.DETAIL) {
				tempResult = matchDetailOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint);
			}else if (pattern.matchMode == MatchMode.AND) {
				tempResult = matchAndOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint);
			}else if (pattern.matchMode == MatchMode.OR) {
				tempResult = matchOrOneTime(aManager,pattern,nodes, lastPoint,maxMatchPoint);
			}else{
				throw new Exception("不正确的类型:" + pattern.matchMode.toString());
			}
			if(tempResult == null){
				if(count >= pattern.minMatchNum && count <=pattern.maxMatchNum){
					//正确匹配
					if(tempList == null){
						 tempList = new ArrayList<QLMatchResultTree>();
					}
					result = new QLMatchResult(tempList,lastPoint);
				}else{
					result = null;
				}
				break;
			}else{
				if(tempList == null){
					 tempList = new ArrayList<QLMatchResultTree>();
				}
				lastPoint = tempResult.matchLastIndex;
				if(pattern.isTreeRoot == true){
					if(tempResult.matchs.size() > 1){
						throw new Exception("根节点的数量必须是1");
					}
					if(tempList.size() == 0){
						tempList.addAll(tempResult.matchs);
					}else{	
						tempResult.matchs.get(0).addLeftAll(tempList);
						tempList = tempResult.matchs;
					}
				}else{
				   tempList.addAll(tempResult.matchs);
				}
			}
			count = count + 1;			
			if(count == pattern.maxMatchNum){
				result = new QLMatchResult(tempList,lastPoint);
				break;
			}
		}
		if(result != null && pattern.isSkip == true){
			//忽略跳过所有匹配到的节点
			result.matchs.clear();
		}

		if(result != null && result.matchs.size() >0 && pattern.rootNodeType != null){
			QLMatchResultTree tempTree = new QLMatchResultTree(pattern.rootNodeType,nodes.get(0).createExpressNode(pattern.rootNodeType,null));
			tempTree.addLeftAll(result.matchs);
			result.matchs.clear();
			result.matchs.add(tempTree);
		}
		return result;
	}

请问支持lambda表达式和匿名函数吗?

return data.stream().filter(d -> d.getKey().equals("code") && Integer.parseInt(d.getValue()) > 200).count();
OR
return data.stream().filter(new Predicate() {
@OverRide
public boolean test(TabMonitorData tabMonitorData) {
return tabMonitorData.getKey().equals("code") && Integer.parseInt(tabMonitorData.getValue()) > 200;
}
}).count();

发现了个bug

public static void main(String[] args) throws Exception {
        ExpressRunner runner = new ExpressRunner();
        DefaultContext<String, Object> context = new DefaultContext<String, Object>();
        String express = "part = \"1@2@3\".split(\"@\");\n" +
                "Integer.valueOf(part[2]);";
        runner.execute(express, context, null, true, false);
}

执行这段代码会报这个错误

Caused by: java.lang.Exception: 没有找到java.lang.Class的方法:valueOf([Ljava.lang.String;)
	at com.ql.util.express.instruction.op.OperatorMethod.executeInner(OperatorMethod.java:96)
	at com.ql.util.express.instruction.op.OperatorBase.execute(OperatorBase.java:67)
	at com.ql.util.express.instruction.detail.InstructionOperator.execute(InstructionOperator.java:44)
	... 8 more

把express的内容改为

part = "1@2@3".split("@");
str = part[2];
Integer.valueOf(str);

就可以了

QLExpress 脚本中异常捕获问题

请问,能在脚本中进行异常捕获吗?当业务逻辑复杂时,需要在脚本中对出现的异常进行捕获,进而进行补偿操作,QLExpress是否支持这种功能?

组合对比有bug

例1
表达式为7<month &&month < 12
key为month
value为9
结果为false

例2
表达式为22<month
key为month
value为100
结果为false

例3
表达式为month < 89
key为month
value为9
结果为false

可以建一个群?

属性访问无法支持Builder模式的GetSet方法

运行环境

JDK 1.8
QLExpress 3.2.2
Windows 10

问题描述

当使用Builder模式的属性时, 系统无法正确读取属性值.

示例代码

public class ELDemoEntity {
    private String name;
    private Long id;
    public String getName() {
        return name;
    }
    public ELDemoEntity setName(String name) {
        this.name = name;
        return this;
    }
    public Long getId() {
        return id;
    }
    public ELDemoEntity setId(Long id) {
        this.id = id;
        return this;
    }
}

@Test
    public void test5() throws Exception {
        ExpressRunner runner = new ExpressRunner(true,true);
        String express = "if(demo.getId()==1)then{demo.id=2};return 0";
        System.out.println(express);

        IExpressContext<String,Object> expressContext = new DefaultContext<String,Object>();
        ELDemoEntity entity = new ELDemoEntity();
        entity.setId(1L).setName("zhangsan");
        expressContext.put("demo", entity);
        Object r = runner.execute(express,
                expressContext, null, false, false);
        System.out.println("r=" + r);
        System.out.println(entity.getId());
    }

错误的堆栈信息

java.lang.Exception: run QlExpress Exception at line 1 :

	at com.ql.util.express.instruction.detail.InstructionOperator.execute(InstructionOperator.java:48)
	at com.ql.util.express.InstructionSet.executeInnerOrigiInstruction(InstructionSet.java:217)
	at com.ql.util.express.InstructionSet.excute(InstructionSet.java:183)
	at com.ql.util.express.InstructionSetRunner.execute(InstructionSetRunner.java:59)
	at com.ql.util.express.InstructionSetRunner.execute(InstructionSetRunner.java:46)
	at com.ql.util.express.InstructionSetRunner.executeOuter(InstructionSetRunner.java:18)
	at com.ql.util.express.ExpressRunner.execute(ExpressRunner.java:587)
	at com.ql.util.express.ExpressRunner.execute(ExpressRunner.java:555)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
...
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
Caused by: java.lang.RuntimeException: 不能访问cn.loopcloud.ELDemoEntity@59d4cd39的property:id
	at com.ql.util.express.ExpressUtil.setProperty(ExpressUtil.java:587)
	at com.ql.util.express.instruction.opdata.OperateDataField.setObject(OperateDataField.java:108)
	at com.ql.util.express.instruction.op.OperatorEvaluate.executeInner(OperatorEvaluate.java:37)
	at com.ql.util.express.instruction.op.OperatorEvaluate.executeInner(OperatorEvaluate.java:18)
	at com.ql.util.express.instruction.op.OperatorBase.execute(OperatorBase.java:67)
	at com.ql.util.express.instruction.detail.InstructionOperator.execute(InstructionOperator.java:44)
	... 30 more
Caused by: java.lang.NoSuchMethodException: Property 'id' has no setter method in class 'class cn.loopcloud.ELDemoEntity'
	at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:2084)
	at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1903)
	at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:2010)
	at org.apache.commons.beanutils.PropertyUtils.setProperty(PropertyUtils.java:896)
	at com.ql.util.express.ExpressUtil.setProperty(ExpressUtil.java:584)
	... 35 more

建议方案

  1. 能否将对象属性, 字段, 方法的操作抽象为接口并支持外部自定义, 这样, 能很方便的支持外部切换对象访问逻辑.
  2. 是否有计划提供比apache beanutils更加高效的属性访问方式, 如字节码访问等, 以提升性能

是否支持操作符< <= > >=当 对象为空的时候返回false

OperatorEqualsLessMore 类
if (obj1 == null && obj2 == null) {
if (opStr.equals("==")) {
return true;
} else if (opStr.equals("!=") || opStr.equals("<>")) {
return false;
} else {
throw new Exception("两个空操作数不能执行这个操作:" + opStr);
}
} else if (obj1 == null || obj2 == null) {
if (opStr.equals("==")) {
return false;
} else if (opStr.equals("!=") || opStr.equals("<>")) {
return true;
} else {
throw new Exception("空操作数不能执行这个操作:" + opStr);
}
}

针对[return -50],如果return后面跟一个负数值时程序解析错误

@Test
public void testChange_1() throws Exception {
    ExpressRunner runner = RuleEngine.newInstance();
    IExpressContext<String, Object> context = new DefaultContext<String, Object>();
    context.put("test", 2.004);
    String test = "if(test > 0){return 50}";
    System.out.println(runner.execute(test, context, null, true, false));

    String test1 = "if(test > 0){return -50}";
    System.out.println(runner.execute(test1, context, null, true, false));
}

从测试用例得出test1执行失败,具体原因应该是在ExpressParse.transferWord2ExpressNode 对'-'这种特殊情况考虑不够。

//返回结果 [1, 2]

//(3)addFunction
ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
runner.addFunction("join",new JoinOperator());
Object r = runner.execute("join(1,2,3)", context, null, false, true);
System.out.println(r);
//返回结果 [1, 2, 3]
结果真的是[1,2,3]吗

17:26:37.341 [main] DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 1
17:26:37.341 [main] DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 2
17:26:37.341 [main] DEBUG com.ql.util.express.instruction.detail.Instruction - LoadData 3
17:26:37.341 [main] DEBUG com.ql.util.express.instruction.detail.Instruction - join(1,2,3)
[1, 2]

能增加个精确错误定位提示吗?

目前的错误提示是这样的:java.lang.Exception: 程序错误,不满足语法规范,没有匹配到合适的语法,最大匹配致[0:2]
没有将分词结果暴露出来,具体错误提示在前端没法显示,不利于快速定位问题

关于if嵌套if语句的疑问!?

您好,大神:
最近在用贵公司的ql,可是发现if里面无法嵌套if语句,比如if(if 1==2 then false else true) then 1 else 2
这种语句无法执行,程序会报:程序错误,不满足语法规范。
请问一下支持类似这种语法吗?已加您微信了,不知道您收到,谢谢大神。

针对数字开头的上下文key支持有问题

下面的测试用例执行会解析不了上下文的值
@test
public void testArithmetic_map() throws Exception {
ExpressRunner runner = new ExpressRunner(true, true);
runner.addMacro("计算平均成绩","(90天浏览时长 + 数学 + 英语)/3");
IExpressContext<String, Object> context =new DefaultContext<String, Object>();
context.put("90天浏览时长", 88);
context.put("数学", 99);
context.put("英语", 95);
System.out.println(runner.execute("计算平均成绩", context, null, true, false));
}

[90天浏览时长]这样的key读取会有问题,具体的错误逻辑应该在ExpressParse.class中的transferWord2ExpressNode,针对数字开头的key没有考虑上述的特殊情况。
不知道还能不能更新啦改项目,我这边自己打个分支先改造了把

InstructionFactory 缓存

InstructionFactory的Map<String,InstructionFactory> instructionFactory 只看到有get , 没看到那里有put

public static InstructionFactory getInstructionFactory(String factory) {
	try {
		InstructionFactory result = instructionFactory.get(factory);
		if (result == null) {
			result = (InstructionFactory) Class.forName(factory)
					.newInstance();
		}
		return result;

java.lang.NoClassDefFoundError

启动的时候报错:
Throwable Occurs during initialization! java.lang.NoClassDefFoundError: org/apache/commons/beanutils/BeanIntrospector#012 at java.lang.Class.forName0(Native Method)#12 at java.lang.Class.forName(Class.java:264)#12 at com.sun.proxy.$Proxy21.(Unknown Source)#12 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)#12 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)#12 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)#12 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)#12 at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:739)#12 at org.apache.commons.configuration2.builder.fluent.Parameters.createParametersProxy(Parameters.java:307)#12 at org.apache.commons.configuration2.builder.fluent.Parameters.fileBased(Parameters.java:186)#12 at org.apache.commons.configuration2.builder.fluent.Configurations.fileParams(Configurations.java:602)#12 at org.apache.commons.configuration2.builder.fluent.Configurations.fileParams(Configurations.java:614)#12 at org.apache.commons.configuration2.builder.fluent.Configurations.fileBasedBuilder(Configurations.java:132)#12 at org.apache.commons.configuration2.builder.fluent.Configurations.propertiesBuilder(Configurations.java:238)#12 at org.apache.commons.configuration2.builder.fluent.Configurations.properties(Configurations.java:282)#12 at me.ele.config.properties.PropertiesFetcher.buildPropertiesMap(PropertiesFetcher.java:257)#12 at me.ele.config.properties.PropertiesFetcher.buildDevFileMap(PropertiesFetcher.java:206)#12 at me.ele.config.properties.DevProperties.(DevProperties.java:18)#12 at me.ele.config.properties.DevProperties.(DevProperties.java:12)#12 at me.ele.config.properties.PropertiesFetcher.buildEnvHoldKey(PropertiesFetcher.java:160)#12 at me.ele.config.properties.PropertiesFetcher.buildSystemHoldMap(PropertiesFetcher.java:110)#12 at me.ele.config.properties.EnvProperties.(EnvProperties.java:14)#12 at me.ele.config.properties.EnvProperties.(EnvProperties.java:11)#12 at me.ele.config.ConfigFactory.(ConfigFactory.java:25)#12 at me.ele.pylon.core.PylonCore.lambda$new$0(PylonCore.java:97)#12 at me.ele.pylon.core.PylonCore.execute(PylonCore.java:294)#12 at me.ele.pylon.core.PylonCore.(PylonCore.java:94)#12 at me.ele.pylon.core.PylonCore.(PylonCore.java:63)#12 at me.ele.pylon.spring.extension.SOAContainerInitializer.postProcessBeanFactory(SOAContainerInitializer.java:37)#12 at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:284)#12 at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:174)#12 at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:678)#12 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:520)#12 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)#12 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)#12 at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)#12 at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)#12 at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)#12 at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)#12 at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)#12 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)#12 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)#12 at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)#12 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)#12 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)#12 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)#12 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)#12 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)#12 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)#12 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)#12 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)#12 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)#12 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)#12 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)#12 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)#12 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)#12 at org.junit.runners.ParentRunner.run(ParentRunner.java:300)#12 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)#12 at org.junit.runner.JUnitCore.run(JUnitCore.java:157)#12 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)#12 at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)#12 at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)#12 at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)#012Caused by: java.lang.ClassNotFoundException: org.apache.commons.beanutils.BeanIntrospector#012 at java.net.URLClassLoader.findClass(URLClassLoader.java:381)#12 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)#12 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)#12 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)#12 ... 63 common frames omitted#012
2018-12-28 17:59:34 INFO [main]: Going to exit with status(-1)!

Process finished with exit code 255

是否考虑List类型数据支持数组操作?

例:

        JSONObject json = new JSONObject();
        json.put("attr", Lists.newArrayList("1", "2", "3"));

        DefaultContext<String, Object> properties = new DefaultContext<String, Object>();
        properties.put("json", json);

        String ex = "json.attr.get(1)";
        Object r = runner.execute(ex, properties, null, true, false);
        System.out.println(r);

        //是否可以支持下面的操作?
//        ex = "json.attr[1]";
//        r = runner.execute(ex, properties, null, true, false);
//        System.out.println(r);

web可视化

有没有可能实现将配置规则web可视化的打算?或者将配置后的规则链表以树的形式展现

有个很想不明白的问题

如图:
image

既然可以通过context传参,为什么还要在express那里填写参数,我觉得这样多次一举了,因为我现在遇到一个需求,我通过不定参数来做到表达式通用化的需求,但如果这样,就会破坏了通用性,而且,我没理解将function添加到runner里面有多方便,本来就是一个方法,直接调用不就得了,为什么调用时还要通过runner再一层包装呢?意义在哪里?

发现一个bug

6.7 - 100 > 39.6 ? 5 == 5 ? 4+5:6-1 : !(100%3-39.0<27) ? 8*2-199: 100%3
这个表达式在3.2.0和3.2.2都无法执行
image

java本身或者其他表达式引擎都是正常的

maven **库没有依赖

com.taobao.util taobao-express 3.0.17 maven **库并没有相应的依赖,这个有计划增加吗?

绑定java类,不能注入bean

我想在绑定的java类中,注入StringRedisTemplate,但是无法注入
@component
public class BeanExample {

@Autowired
private StringRedisTemplate stringRedisTemplate;


public boolean redisTest(String key) {
    stringRedisTemplate.opsForValue().set(key, "shfskfhoifhjls");
    return stringRedisTemplate.hasKey(key);
}

},我想注入StringRedisTemplate,这样做可以吗

脚本中使用spring注入报错

Time:23 ms - ID:com.midea.dataexporter.demo.mapper.UserMapper.selectList
Execute SQL:SELECT test_id AS id,name,age,test_type,test_date,role,phone,tenant_id FROM user

java.lang.RuntimeException: 没有实现方法:getObjectInner

at com.ql.util.express.instruction.opdata.OperateDataKeyValue.getObjectInner(OperateDataKeyValue.java:38)

数组类型推断有问题

@Test
public void testFunction2() throws Exception {
    ExpressRunner runner = new ExpressRunner();
    String exp = "System.out.println(args[0]);";
    String[] args = {"123","456"};
    IExpressContext<String, Object> context = new DefaultContext<String, Object>();
    ((DefaultContext<String, Object>) context).put("args", args);
    Object result = runner.execute(exp,context,null,false,false);
}

发现上面这段代码在实际运行时调用的方法是
public void java.io.PrintStream.println(java.lang.Object)
却不是
public void java.io.PrintStream.println(java.lang.String)
debug时发现findMethod的type是class [Ljava.lang.String;
请问这是一个bug还是开发时特意保留的特性?

附debug到com.ql.util.express.ExpressUtil#findMethod的debugger截图
image

Expression Language Injection Security Risk

Just like spring el\ognl\jstl,alibba QLexpress alse allow programmer to directly call the Java Object to execute the method using the java reflection mechanism,
image
but there is no any security restrictions that rise a security risk while editing rules, just like that poc:
image
so,that cause a remote code execution;
Although it is a feature, there are security risks in design.
fix:

  1. Use java.lang.SecurityManager to protected JVM;
  2. Prevent against by blacklist(Runtime\ ScriptEngine\FileAccess...);
  3. Create a property setting that allows access to java or not.
    see more at:
    https://wooyun.js.org/drops/%E4%B8%80%E7%A7%8D%E6%96%B0%E7%9A%84%E6%94%BB%E5%87%BB%E6%96%B9%E6%B3%95%E2%80%94%E2%80%94Java-Web-Expression-Language-Injection.html
    https://www.owasp.org/index.php/Expression_Language_Injection
    http://danamodio.com/tag/expression-language-injection/
    https://www.owasp.org/images/7/7e/Owasp_SSTI_final.pdf
    @baoxingjie

内存泄漏问题

5: 2692930 64630320 com.ql.util.express.OperateData
6: 2692720 64625280 com.ql.util.express.instruction.detail.InstructionConstData
存在大量未回收对象,请问如何可以避免呢

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.