我的开源:规则编排调度器与实践(防刷、抽奖)

目录

源码位置

1. what

2. 原理

3. 图示

4. 应用场景

5. 测试代码


源码位置

https://github.com/chlInGithub/ruledispatcherhttps://github.com/chlInGithub/ruledispatcher

1. what

不像Drools,不是复杂的规则引擎,而是负责规则的编排和调度。它适用于常规业务系统,也适用于saas系统。它让开发者仅需要关注规则的业务逻辑。

2. 原理

2.1. 规则编排的维度

规则编排按照场景种类+应用种类+规则种类三个维度进行编排。

2.2. 规则调度的方式

从场景种类+应用种类维度进行调度,支持的规则执行方式:

  • 具体规则种类
  • 所有规则种类
  • 命中一条规则即返回
  • 兜底规则
  • 规则优先级

2.3. Spring扩展点

BeanFactoryPostProcessor

2.4. 自定义注解

3. 图示

如图可以看出,零散的规则控制器,经过编排后,成为了组织清晰的结构,支持多种规则调度玩法。还可以看出,开发者仅需要关注规则控制器即可。

我的开源:规则编排调度器与实践(防刷、抽奖)_第1张图片

下图分为两个部分展示了调度流程:

我的开源:规则编排调度器与实践(防刷、抽奖)_第2张图片

4. 应用场景

基于灵活扩展的考虑,我设计并实现了规则编排调度器,并且在实际需求中进行了应用。源码提供的规则编排调度器,已经进行了抽象,不局限于特定某些规则使用场景。接下来,我列举几个在实践工作中的应用场景。例如使用场景,防刷机制、商品价格调整建议、等等。

4.1. 异常登录

依据设备、登录账号、时间周期三个主要维度进行异常登录的拦截、登录统计、 异常登录的判断。

将拦截作为事前规则,统计作为事中规则,判断与持久化作为事后规则,按照场景、应用、规则维度进行编排,调用时传入场景和应用即可按照上述规则进行调度。

4.2. 抽奖

抽奖场景包括两个基本的数据模型,即活动和奖品。

每一个活动,可以配置多种规则,如参与日期时间、参与的用户身份要求、参与次数、中奖次数限制、每次参与的消耗等。

每个奖品,也可以配置多种规则,如库存、中奖次数、中奖用户身份要求等。 针对一个规则,可能包含多种子类型规则,如中奖次数规则,可以是每轮限制、具体日期后限制等。

基于上述的描述,我将每个配置规则定义为可执行的规则,按照事前、事中、事后进行划分。事前规则包括限制类、验证类的规则,事后规则包括库存扣减、中奖限制等规则。

具体的规则如下:

我的开源:规则编排调度器与实践(防刷、抽奖)_第3张图片​​​​​​​

 

5. 测试代码

@Data
public class TrainRuleDispatcherContext extends RuleDispatcherContext {

    /**
     * 规则需要的入参s
     */
    Integer param;

    /**
     * 前置处理的过程数据
     */
    String valFromPreAction;

    /**
     * 后置处理的过程数据
     */
    String valFromAfterAction;

    /**
     * 某个规则的过程数据
     */
    String val2;

    /**
     * 某个规则的过程数据
     */
    String val3;
}

@AsPreAction(scene = "train", app = "app1")
@Component
public class TrainChlPreAction extends PreAction {

    @Override
    protected boolean handle(TrainRuleDispatcherContext ruleDispatcherContext) {
        ruleDispatcherContext.setValFromPreAction("val from preAction");
        if (ruleDispatcherContext.getParam() == null) {
            return true;
        }
        return false;
    }
}

@AsAfterAction(scene = "train", app = "app1")
@Component
public class TrainChlAfterAction extends AfterAction {

    @Override
    protected void handle(TrainRuleDispatcherContext ruleDispatcherContext) {
        ruleDispatcherContext.setValFromAfterAction("val from afterAction");
    }
}

@Slf4j
public class TrainChlBaseRuleHandler extends RuleHandler {

    @Override
    protected boolean match(TrainRuleDispatcherContext param) {
        log.info("TrainBaseRuleHandler matching");
        return param.getParam() > 10;
    }

    @Override
    protected void action(TrainRuleDispatcherContext param) {
        log.info("TrainBaseRuleHandler actioning");
    }
}

@AsRuleHandler(scene = "train", app = "app1", rule = "rule1", priority = 10)
@Component
@Slf4j
public class TrainChlRuleHandler01 extends TrainChlBaseRuleHandler {

    @Override
    protected boolean match(TrainRuleDispatcherContext param) {
        log.info(this.getClass().getName() + " matching");
        return super.match(param);
    }

    @Override
    protected void action(TrainRuleDispatcherContext param) {
        super.action(param);
        log.info(this.getClass().getName() + " actioning");
        param.setVal2("val from " + this.getClass().getName());
    }
}

@AsRuleHandler(scene = "train", app = "app1", rule = "rule2", priority = 5)
@Component
@Slf4j
public class TrainChlRuleHandler02 extends TrainChlBaseRuleHandler {

    @Override
    protected boolean match(TrainRuleDispatcherContext param) {
        log.info(this.getClass().getName() + " matching");
        return param.getParam() > 20;
    }

    @Override
    protected void action(TrainRuleDispatcherContext param) {
        log.info(this.getClass().getName() + " actioning");
        param.setVal3("val from " + this.getClass().getName());
    }
}

@Component
public class TrainChlRuleDispatcherEntrance implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 规则编排
        RuleDispatcher.arrange(beanFactory);
        // 规则调度
        trainRuleDispatcher();
        // 查看规则编排的结果
        System.out.println(RuleDispatcher.getNodes());
    }

    void trainRuleDispatcher() {
        TrainRuleDispatcherContext ruleDispatcherContext = new TrainRuleDispatcherContext();
        ruleDispatcherContext.setScene("train");
        ruleDispatcherContext.setApp("app1");
        ruleDispatcherContext.setParam(15);
        RuleDispatcher.dispatch(ruleDispatcherContext);
        System.out.println(ruleDispatcherContext);

        ruleDispatcherContext = new TrainRuleDispatcherContext();
        ruleDispatcherContext.setScene("train");
        ruleDispatcherContext.setApp("app1");
        ruleDispatcherContext.setParam(25);
        RuleDispatcher.dispatch(ruleDispatcherContext);
        System.out.println(ruleDispatcherContext);

        ruleDispatcherContext = new TrainRuleDispatcherContext();
        ruleDispatcherContext.setScene("train");
        ruleDispatcherContext.setApp("app1");
        ruleDispatcherContext.setRule("rule1");
        ruleDispatcherContext.setParam(15);
        RuleDispatcher.dispatch(ruleDispatcherContext);
        System.out.println(ruleDispatcherContext);

        ruleDispatcherContext = new TrainRuleDispatcherContext();
        ruleDispatcherContext.setScene("train");
        ruleDispatcherContext.setApp("app1");
        ruleDispatcherContext.setRule("rule2");
        ruleDispatcherContext.setParam(15);
        RuleDispatcher.dispatch(ruleDispatcherContext);
        System.out.println(ruleDispatcherContext);
    }

你可能感兴趣的:(技术思考总结,PostProcessor,Spring扩展点,规则编排,规则调度)