一个轻量级的规则引擎、搜索引擎,让条件匹配简单、优雅。
GIT地址
https://gitcode.cosmoplat.com/15011240224/rule-engine-starter
介绍
Rule-Engine-Starter 是一个轻量级规则引擎,V1.0.0主要解决条件匹配问题。比如飞书文档,每个文档都可以设置访问权限,可以限制哪些人、哪些部门可以访问、是否对互联网用户公开等等,这些条件可以看成每个文档设置的访问规则,一个文档可以设置多个规则。
校验一个用户是否能访问目标文档,只需要校验规则中的条件,可以使用SPEL等表达式来实现;但是如果想获取一个用户有访问权限的所有文档,如果再用SPEL实现岂不是需要遍历所有文档的所有规则,这种方案无疑是低效的。因此自研 Rule-Engine-Starter 解决这个问题,只需要将用户的属性作为条件输入给规则引擎,规则引擎会快速返回所有匹配的规则:
Rule-Engine-Starter 通过拉平条件和MySQL的B+Tree索引实现快速匹配。
Demo
访问地址:https://gitcode.cosmoplat.com/15011240224/rule-engine-demo
修改数据库配置后,可本地执行com.cosmoplat.rule.RuleTest。
使用
-
MySQL初始化,执行src/main/sql/init.sql
-
POM引入依赖和卡奥斯仓库
<dependency><groupId>com.cosmoplat.rule</groupId><artifactId>rule-engine-starter</artifactId><version>1.0.0</version>
</dependency><repository><id>maven-public</id><name>maven-public</name><url>http://nexus.cosmoplat.com/repository/maven-public/</url><snapshots><enabled>true</enabled></snapshots>
</repository>
-
修改配置文件
spring:datasource:url: jdbc:mysql://xxx.xxx.xxx.xxx:xxxxx/库名username: 用户名password: 密码driver-class-name: com.mysql.cj.jdbc.Driver# 启用规则引擎 rule:engine:enabled: true
-
创建维度
Dimension dimension = Dimension.builder().namespaceId(NAMESPACE_ID).code(dimensionEnum.getCode()).description(dimensionEnum.getName()).build(); ruleEngineService.createDimensions(Collections.singletonList(dimension));
-
创建分类
List<String> dimension = Lists.newArrayList(DimensionEnum.WORK_NO.getCode(), DimensionEnum.DEPT_NO.getCode()); Type ruleType = Type.builder().code(DOC_READ_RULE_TYPE_CODE).description("文档阅读规则").namespaceId(NAMESPACE_ID).dimensionCodes(dimension).build(); ruleEngineService.createTypes(Lists.newArrayList(ruleType));
-
添加规则
String docId1= "11111";
String docId2= "22222";
String docId3= "33333";
// 允许体验云和海云智造的员工阅读文档1
createDocReadRule(docId1, Lists.newArrayList(ALL), Lists.newArrayList("tiYanYun", "haiyunzhizao"));
// 只允许工号22038425阅读文档2
createDocReadRule(docId2, Lists.newArrayList("22038425"), Lists.newArrayList(ALL));
// 只允许工号77889998阅读文档3
createDocReadRule(docId3, Lists.newArrayList("77889998"), Lists.newArrayList(ALL));private void createDocReadRule(String docId, List<String> workNos, List<String> deptNos) throws RuleConflictException {Package rule = new Package();rule.setNamespaceId(NAMESPACE_ID);rule.setTypeCode(DOC_READ_RULE_TYPE_CODE);rule.setName("文档阅读规则");rule.setCreateInfo();// 匹配结果rule.setConfigInfo(docId);// 规则条件Map<String, List<String>> searchKeyMap = Maps.newHashMap();searchKeyMap.put(DimensionEnum.WORK_NO.getCode(), workNos);searchKeyMap.put(DimensionEnum.DEPT_NO.getCode(), deptNos);ruleEngineService.createRule(rule, searchKeyMap);
}
-
规则匹配
// 规则匹配,返回体验云员工22038425能访问的文档 Map<String, List<String>> searchAndSortKeyMap = Maps.newHashMap(); searchAndSortKeyMap.put(DimensionEnum.WORK_NO.getCode(), Lists.newArrayList( "22038425", ALL)); searchAndSortKeyMap.put(DimensionEnum.DEPT_NO.getCode(), Lists.newArrayList("tiYanYun", ALL)); List<MatchRuleResult<String>> ret = ruleEngineService.matchRule(NAMESPACE_ID,DOC_READ_RULE_TYPE_CODE, searchAndSortKeyMap, null);List<String> docIds = ret.stream().map(MatchRuleResult::getResult).collect(toList()); Assert.isTrue(docIds.contains(docId1), "文档1不能阅读"); Assert.isTrue(docIds.contains(docId2), "文档2不能阅读"); Assert.isTrue(!docIds.contains(docId3), "文档3能阅读");
支持
如果您觉得有用,麻烦您按照链接支持下:链接