QLExpress入门
介绍:
QLExpress 是一个轻量级的类java语法规则引擎,作为一个嵌入式规则引擎在业务系统中使用。
规则引擎和流程引擎一起,是使用在大规模复杂业务场景下必备的业务框架技术,使用这两门技术搭建起来的系统能够很好的梳理清楚业务逻辑,并且方便快速的修改业务逻辑,甚至可以做到需求的实时生效。
规则引擎最大的价值就在于通过以下的三个过程,大大的缓解了频繁的需求变化给整个业务系统带来的灾难。
- 逼迫系统开发人员和业务专家梳理业务,定义统一的BOM(业务对象模型)。
- 业务专家可以快速的制定修改规则,然后交由规则引擎自动化地来处理分析。
- 规则引擎代替系统开发人员,解决由规则条件关联动作变化带来的开发工作。
相关文档:
https://yq.aliyun.com/articles/621206/
下面写一个例子,简单展示下它的使用
1:项目结构如图所示
2.详细代码
首先导入jar包
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>QLExpress</artifactId>
<version>3.2.0</version>
</dependency>
- 实体类
import lombok.Data;
/**
* @author:Zhr date:2021/12/9 16:08
* @desc:人员类,包含基本信息
*/
@Data
public class QlPerson {
private String name;
private Integer age;
private Integer sex;
}
- 规则枚举类
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author:Zhr date:2021/12/9 16:03
* @desc:基础规则枚举类
*/
@AllArgsConstructor
public enum ConditionEnum {
MALE("是男性","性别为男(person,1)"),
FEMALE("是女性","性别为男(person,0)"),
OVER60("年龄达到60岁","是否达到退休年龄(person,60)"),
OVER50("年龄达到50岁","是否达到退休年龄(person,50)");
@Getter
private String macroName;
@Getter
private String express;
}
- 测试主类
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author:Zhr date:2021/12/9 15:54
* @desc:测试类
*/
@Data
public class QlExpTest {
public static ExpressRunner expressRunner;
static {
//将加载规则等相关初始化工作放在static代码块中,保证规则先加载完毕,也可以写个初始化方法,先执行init方法也可以
try{
//构造执行器
expressRunner = new ExpressRunner();
//添加规则
expressRunner.addOperatorWithAlias("如果","if",null);
expressRunner.addOperatorWithAlias("则","then",null);
expressRunner.addOperatorWithAlias("否则","else",null);
expressRunner.addOperatorWithAlias("或者","or",null);
expressRunner.addOperatorWithAlias("并且","and",null);
//注册自定义方法
expressRunner.addFunctionOfClassMethod("性别为男",QlExpTest.class.getName(),"isBoy",new Class[]{QlPerson.class,int.class},null);
expressRunner.addFunctionOfClassMethod("是否达到退休年龄",QlExpTest.class.getName(),"isOver60",
new Class[]{QlPerson.class,int.class},null);
//从枚举类里加载规则对应自定义方法,与上面的定义方法步骤一定要按照顺序不可颠倒否则会报Runner找不到XX规则或XXX自定义方法(这一步也可如下方注释一样添加)
for (ConditionEnum conditionEnum: ConditionEnum.values()){
expressRunner.addMacro(conditionEnum.getMacroName(), conditionEnum.getExpress());
}
/* expressRunner.addMacro("是男性","性别为男(person,1)");
expressRunner.addMacro("是女性","性别为男(person,0)");
expressRunner.addMacro("年龄达到60岁","是否达到退休年龄(person,60)");
expressRunner.addMacro("年龄达到50岁","是否达到退休年龄(person,50)");*/
}catch (Exception e){
e.printStackTrace();
}
}
//自定义方法判断是否为男性
public boolean isBoy(QlPerson person,int sex){
if(person.getSex()==sex)
return true;
return false;
}
//自定义方法判断年龄
public boolean isOver60(QlPerson person, int age){
if(person.getAge()>age)
return true;
return false;
}
//判断方法,传入参数和规则
public static void judge(QlPerson person, String express) throws Exception {
IExpressContext<String,Object> expressContext = new DefaultContext<>();
expressContext.put("person",person);
List<String> errorInfo = new ArrayList<>();
//执行
Object result = expressRunner.execute(express, expressContext, errorInfo, false, false);
System.out.println("result"+result);
}
//测试
public static void main(String[] args) throws Exception {
//模板规则 会根据此规则进行解析执行(通过读文件或读库方式加载,让产品自己来写规则)
String exp = "如果((是男性 并且 年龄达到60岁) 或者 (是女性 并且 年龄达到50岁))" +
" 则 {return '休息';} " + "否则 {return '工作';}";
QlPerson person = new QlPerson();
person.setSex(1);
person.setName("zs");
person.setAge(59);
judge(person,exp);
}
}
执行结果
改变参数1 ,65