一、场景
前一篇,介绍了Easy Rules作为Java一款轻量级的规则引擎,使得研发更加注重于纯业务开发,提高开发效率。
这一篇,主要是围绕,规则配置数据,外置于数据库Mysql的实现。
二、思路
1、Mysql存储
新建表t_biz_rule、t_biz_rule_compose分别存储规则定义、规则组合定义
2、构建Rules
-
Mysql中的Rule、RuleCompose转换成RuleDefinition对象
-
定义Rules注册工具类Helper,为每个RuleCompose注册
3、定义Facts以及RulesEngine
三、实现
1、Mysql实现规则配置的CRUD
定义对象BizRule
@Data
@Accessors(chain = true)
public class BizRule implements Serializable {
/*** 主键ID*/
private Long id;
/*** 规则组*/
private String groupCode;
/*** 规则名称*/
private String name;
/*** 规则描述*/
private String description;
/*** 规则权重*/
private int priority;
/*** 规则组合类型(compositeRuleType)* {
@link CompositeRuleTypeEnum}*/
private Integer compositeType;
/*** 状态 0有效-1无效*/
private Integer status;
/*** 创建时间*/
private Date createTime;
/*** 变更时间*/
private Date updateTime;
}
定义对象BizRuleCompose
@Data
@Accessors(chain = true)
public class BizRuleCompose implements Serializable {
?/*** 主键ID*/private Long id;
?/*** 规则ID*/private Long ruleId;
?/*** 规则名称*/private String name;
?/*** 规则描述*/private String description;
?/*** 规则权重*/private int priority;
?/*** 规则条件(Java代码)*/private String condition;
?/*** 执行操作*/private String actions;
?/*** 状态 0有效-1无效*/private Integer status;/*** 创建时间*/private Date createTime;
}
定义CRUD参数Bo
@Data
public class BizRuleBo implements Serializable {
?/*** 名称*/@NotNull(message = "请输入规则名称")@Size(min = 2, max = 50, message = "规则名称2-50个字符")private String name;
?/*** 描述*/@NotNull(message = "请输入规则描述")@Size(min = 2, max = 20, message = "规则名称2-10个字符")private String description;
?/*** 规则组*/@NotNull(message = "请定义规则组")@Size(min = 2, max = 10, message = "规则名称2-10个字符")private String groupCode;
?/*** 权限*/private int priority;
?/*** 组合类型*/private Integer compositeType;
?/*** 组合规则*/private List<BizComposeBo> composingRules;
}
新增规则的API实现
@RestController
@RequestMapping("biz_rule")
@AllArgsConstructor
@Validated
public class BizRuleController {
?private BizRuleService bizRuleService;
?@AuthIgnore@PostMapping("/add")@OperationLog(value = "业务规则新建", type = LogOperationEnum.ADD)public ResultVo<Integer> add(@RequestBody @Valid BizRuleBo bo) {
return ResultVo.success(bizRuleService.addRule(bo));}
}
POST请求结果
2、通过Heler工具类构建Rules对象
定义BizRuleHelper
public class BizRuleHelper extends AbstractRuleFactory {
?private final ParserContext parserContext;
?public BizRuleHelper(ParserContext parserContext) {
this.parserContext = parserContext;}
?
?/*** 创建规则* @param ruleDefinitions 规则定义* @return 结果*/public Rules createRules(List<RuleDefinition> ruleDefinitions) {
Rules rules = new Rules();ruleDefinitions.forEach(ruleDefinition -> rules.register(createRule(ruleDefinition)));return rules;}
?@Overridepublic Rule createSimpleRule(RuleDefinition ruleDefinition) {
MVELRule mvelRule = new MVELRule(parserContext).name(ruleDefinition.getName()).description(ruleDefinition.getDescription()).priority(ruleDefinition.getPriority()).when(ruleDefinition.getCondition());for (String action : ruleDefinition.getActions()) {
mvelRule.then(action);}return mvelRule;}
}
定义RulesConfig
@Component
@AllArgsConstructor
public class BizRulesConfig {
?private BizRuleService bizRuleService;
?static String group_code = "order_rule";
?/*** 构建rules配置*/public Rules fetchConfigRules() {
//JSON 表达式BizRuleHelper bizRuleHelper = new BizRuleHelper(new ParserContext());return bizRuleHelper.createRules(bizRuleService.ruleDefinitions(group_code));}
}
3、API代码
@AuthIgnore@OperationLog(value = "easy rules DB测试")@PostMapping("/db")@SneakyThrowspublic ResultVo<?> dbTest(@RequestBody BizOrder order) {
//定义数据Facts facts = new Facts();facts.put("param", order);facts.put("OrderService",OrderService.class);//读取配置Rules rules = bizRulesConfig.fetchConfigRules();//引擎配置RulesEngine rulesEngine = new DefaultRulesEngine();rulesEngine.fire(rules, facts);return ResultVo.success();}
4、场景模拟
和前一篇类似,模拟商品1,是打折商品,原价200,折扣7折,计算最后价格。
POST模拟请求参数
代码逻辑处理
我们可以看出,通过调用统一接口/order/db,最终还是执行了折扣的业务逻辑。
完!