通过模板模式,整合责任链、规则树,定义出抽奖的标准过程。以及让子类做具体调用功能实现。将上一节中的规则树结构设计整合到抽奖过程中。这样整个抽奖过程就会包括:责任链进行抽奖前的规则过滤并计算抽奖结果,基于抽奖结果再进行规则树的过滤,最终返回抽奖结果

开发流程

  1. 增加3个po,组装树的po
  2. 增加3个po对应的dao操作 视频7分钟
  3. 定义dao 对应的mybatis mapper,映射到mysql,并集中在RuleTreeDaoTest中测试,发现了一个bug,在[[Bug记录]]
  4. 在仓库StrategyRepository定义queryRuleTreeVOByTreeId函数。可以在redis中存下来这样的树型结构(根据数据库中ruleTree,ruleTreeNode,ruleTreeNodeLine)构建
  5. 重构抽奖流程

    之前的performRaffle(raffleFactorEntity)流程是
    1. 进行抽奖因子的参数校验,userId, strategyId是否合法
    2. 通过责任链工厂获得责任链defaultChainFactory.openLogicChain(strategyId)
    3. 通过责任链进行抽奖 拿到奖品id
    4. 根据奖品id查询对应的奖品规则进行过滤。兜底奖励,次数锁,库存处理等 返回最终结果

    因此从上看出来在责任链的过程中。rule_blacklist --> rule_weight ->default. 不是所有规则都需要走后续的处理,比如如果是黑名单直接返回结果就行了。所以需要改造 logic的返回类型,之前都是Integer logic(String userid, Long strategyId) 直接返回奖品id。现在在责任链工厂DefaultChainFactory中 新增奖品实体对象StrategyAwardVO有两个属性awardId LogicModel
  6. 在AbstractRaffleStrategy中定义raffleLogicChain方法和raffleLogicTree方法。重构实现performRaffle。在子类DefaultRaffleStrategy中实现上述两个方法
    重构前的代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    @Override  
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
    //1. 参数校验
    String userId = raffleFactorEntity.getUserId();
    Long strategyId = raffleFactorEntity.getStrategyId();
    if (strategyId == null || StringUtils.isBlank(userId)){
    throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
    }

    // 2. 获取抽奖责任链 - 前置规则的责任链处理
    ILogicChain logicChain = defaultChainFactory.openLogicChain(strategyId);

    //3.通过责任链获得奖品id
    Integer awardId = logicChain.logic(userId, strategyId);


    //4.拿到奖品id后,查询对应的奖品规则
    //抽奖中:awardId 对应的 ruleModel有可能的rule_lock和 rule_luck_award进行次数规则过滤
    //抽奖后:扣减完奖品库存后过滤,抽奖中拦截和无库存走兜底奖品
    StrategyAwardRuleModelVO strategyAwardRuleModelVO = repository.queryStrategyAwardRuleModelVO(strategyId, awardId);
    log.info("拿到strategyawardRuleModel:{}",strategyAwardRuleModelVO.getRuleModels());

    //5. 抽奖中 - 规则过滤
    //将只有是抽奖中的规则传入doCheckRaffleCenter函数中
    RuleActionEntity<RuleActionEntity.RaffleCenterEntity> ruleActionCenterEntity = this.doCheckRaffleCenterLogic(RaffleFactorEntity.builder()
    .userId(userId)
    .strategyId(strategyId)
    .awardId(awardId)
    .build(),strategyAwardRuleModelVO.raffleCenterRuleModelList());

    if (RuleLogicCheckTypeVO.TAKE_OVER.getCode().equals(ruleActionCenterEntity.getCode())){
    log.info("[临时日志]:抽奖中 规则过滤,用户抽奖次数小于ruleValue,走rule_luck_award过滤规则");
    return RaffleAwardEntity.builder()
    .awardDesc("用户抽奖次数小于ruleValue,走rule_luck_award过滤规则")
    .build();
    }

    return RaffleAwardEntity.builder()
    .awardId(awardId)
    .build();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    @Override  
    protected RuleActionEntity<RuleActionEntity.RaffleCenterEntity> doCheckRaffleCenterLogic(RaffleFactorEntity raffleFactorEntity, String... logics) {
    //1.检查传入的ruleModel是否为空
    if (logics == null || logics.length == 0) return RuleActionEntity.<RuleActionEntity.RaffleCenterEntity>builder()
    .code(RuleLogicCheckTypeVO.ALLOW.getCode())
    .info(RuleLogicCheckTypeVO.ALLOW.getInfo())
    .build();
    //2.获取过滤器logicFilterGroup
    Map<String, ILogicFilter<RuleActionEntity.RaffleCenterEntity>> logicFilterMap = logicFactory.openLogicFilter();

    RuleActionEntity<RuleActionEntity.RaffleCenterEntity> ruleActionEntity = null;
    //3. 遍历logics进行规则过滤
    for(String ruleModel : logics){
    RuleMatterEntity ruleMatterEntity = new RuleMatterEntity();
    ruleMatterEntity.setUserId(raffleFactorEntity.getUserId());
    ruleMatterEntity.setStrategyId(raffleFactorEntity.getStrategyId());
    ruleMatterEntity.setAwardId(raffleFactorEntity.getAwardId());
    ruleMatterEntity.setRuleModel(ruleModel);
    ILogicFilter<RuleActionEntity.RaffleCenterEntity> logicFilter = logicFilterMap.get(ruleModel);
    ruleActionEntity = logicFilter.filter(ruleMatterEntity);
    log.info("抽奖中规则过滤 userId: {} ruleModel: {} code: {} info: {}", raffleFactorEntity.getUserId(), ruleModel, ruleActionEntity.getCode(), ruleActionEntity.getInfo());
    if (!RuleLogicCheckTypeVO.ALLOW.getCode().equals(ruleActionEntity.getCode())) return ruleActionEntity;
    }


    return ruleActionEntity;
    }

连线 节点 整颗树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
连线Map {rule_from:{ruleTreeLineList}}
{
"rule_lock":[
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"ALLOW",
"ruleNodeFrom":"rule_lock",
"ruleNodeTo":"rule_stock",
"treeId":"tree_lock"
},
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"TAKE_OVER",
"ruleNodeFrom":"rule_lock",
"ruleNodeTo":"rule_luck_award",
"treeId":"tree_lock"
}
],
"rule_stock":[
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"TAKE_OVER",
"ruleNodeFrom":"rule_stock",
"ruleNodeTo":"rule_luck_award",
"treeId":"tree_lock"
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
节点map {rule_key: ruleTreeNode}
{
"rule_lock":{
"ruleDesc":"限定用户已完成N次抽奖后解锁",
"ruleKey":"rule_lock",
"ruleValue":"1",
"treeId":"tree_lock",
"treeNodeLineVOList":[
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"ALLOW",
"ruleNodeFrom":"rule_lock",
"ruleNodeTo":"rule_stock",
"treeId":"tree_lock"
},
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"TAKE_OVER",
"ruleNodeFrom":"rule_lock",
"ruleNodeTo":"rule_luck_award",
"treeId":"tree_lock"
}
]
},
"rule_stock":{
"ruleDesc":"库存扣减规则",
"ruleKey":"rule_stock",
"treeId":"tree_lock",
"treeNodeLineVOList":[
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"TAKE_OVER",
"ruleNodeFrom":"rule_stock",
"ruleNodeTo":"rule_luck_award",
"treeId":"tree_lock"
}
]
},
"rule_luck_award":{
"ruleDesc":"兜底奖品随机积分",
"ruleKey":"rule_luck_award",
"ruleValue":"1,100",
"treeId":"tree_lock"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
ruleTree
{
"treeDesc":"规则树",
"treeId":"tree_lock",
"treeName":"规则树",
"treeNodeMap":{
"rule_lock":{
"ruleDesc":"限定用户已完成N次抽奖后解锁",
"ruleKey":"rule_lock",
"ruleValue":"1",
"treeId":"tree_lock",
"treeNodeLineVOList":[
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"ALLOW",
"ruleNodeFrom":"rule_lock",
"ruleNodeTo":"rule_stock",
"treeId":"tree_lock"
},
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"TAKE_OVER",
"ruleNodeFrom":"rule_lock",
"ruleNodeTo":"rule_luck_award",
"treeId":"tree_lock"
}
]
},
"rule_stock":{
"ruleDesc":"库存扣减规则",
"ruleKey":"rule_stock",
"treeId":"tree_lock",
"treeNodeLineVOList":[
{
"ruleLimitType":"EQUAL",
"ruleLimitValue":"TAKE_OVER",
"ruleNodeFrom":"rule_stock",
"ruleNodeTo":"rule_luck_award",
"treeId":"tree_lock"
}
]
},
"rule_luck_award":{
"ruleDesc":"兜底奖品随机积分",
"ruleKey":"rule_luck_award",
"ruleValue":"1,100",
"treeId":"tree_lock"
}
},
"treeRootRuleNode":"rule_lock"
}