Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
KnowledgePlanet
road-map
xfg-frame-archetype-lite
提交
070b7cdd
xfg-frame-archetype-lite
项目概览
KnowledgePlanet
/
road-map
/
xfg-frame-archetype-lite
通知
1644
Star
80
Fork
96
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
xfg-frame-archetype-lite
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
070b7cdd
编写于
4月 13, 2024
作者:
H
hudingrong
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
before_filter_prule
上级
d9161499
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
754 addition
and
0 deletion
+754
-0
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml
...rc/main/resources/mybatis/mapper/strategy_rule_mapper.xml
+7
-0
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/ApiTest.java
...type-lite-app/src/test/java/cn/bugstack/test/ApiTest.java
+7
-0
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java
...test/java/cn/bugstack/test/domain/RaffleStrategyTest.java
+65
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/AwardEntity.java
...cn/bugstack/domain/strategy/model/entity/AwardEntity.java
+25
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleAwardEntity.java
...stack/domain/strategy/model/entity/RaffleAwardEntity.java
+44
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java
...tack/domain/strategy/model/entity/RaffleFactorEntity.java
+25
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RuleActionEntity.java
...gstack/domain/strategy/model/entity/RuleActionEntity.java
+59
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RuleMatterEntity.java
...gstack/domain/strategy/model/entity/RuleMatterEntity.java
+23
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
...ck/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
+23
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
...stack/domain/strategy/repository/IStrategyRepository.java
+9
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStrategy.java
.../cn/bugstack/domain/strategy/service/IRaffleStrategy.java
+20
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/annotation/LogicStrategy.java
...ack/domain/strategy/service/annotation/LogicStrategy.java
+21
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/AbstractRaffleStrategy.java
...omain/strategy/service/raffle/AbstractRaffleStrategy.java
+86
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java
...domain/strategy/service/raffle/DefaultRaffleStrategy.java
+88
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/ILogicFilter.java
...n/bugstack/domain/strategy/service/rule/ILogicFilter.java
+16
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/factory/DefaultLogicFactory.java
...in/strategy/service/rule/factory/DefaultLogicFactory.java
+53
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/impl/RuleBackListLogicFilter.java
...n/strategy/service/rule/impl/RuleBackListLogicFilter.java
+65
-0
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/impl/RuleWeightLogicFilter.java
...ain/strategy/service/rule/impl/RuleWeightLogicFilter.java
+102
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java
...stack/infrastructure/persistent/dao/IStrategyRuleDao.java
+7
-0
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java
...rastructure/persistent/repository/StrategyRepository.java
+9
-0
未找到文件。
xfg-frame-archetype-lite-app/src/main/resources/mybatis/mapper/strategy_rule_mapper.xml
浏览文件 @
070b7cdd
...
@@ -24,5 +24,12 @@
...
@@ -24,5 +24,12 @@
from strategy_rule
from strategy_rule
where strategy_id = #{strategyId} and rule_model = #{ruleModel}
where strategy_id = #{strategyId} and rule_model = #{ruleModel}
</select>
</select>
<select
id=
"queryStrategyRuleValue"
parameterType=
"cn.bugstack.infrastructure.persistent.po.StrategyRule"
resultType=
"java.lang.String"
>
select rule_value from strategy_rule
where strategy_id = #{strategyId} and rule_model = #{ruleModel}
<if
test=
"awardId != null"
>
and award_id = #{awardId}
</if>
</select>
</mapper>
</mapper>
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/ApiTest.java
浏览文件 @
070b7cdd
...
@@ -16,4 +16,11 @@ public class ApiTest {
...
@@ -16,4 +16,11 @@ public class ApiTest {
log
.
info
(
"测试完成"
);
log
.
info
(
"测试完成"
);
}
}
@Test
public
void
test1
()
{
String
testSplit
=
"abc 123"
;
String
[]
s
=
testSplit
.
split
(
"d"
);
System
.
out
.
println
(
s
[
0
]);
}
}
}
xfg-frame-archetype-lite-app/src/test/java/cn/bugstack/test/domain/RaffleStrategyTest.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.test.domain
;
import
cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity
;
import
cn.bugstack.domain.strategy.service.IRaffleStrategy
;
import
cn.bugstack.domain.strategy.service.rule.impl.RuleWeightLogicFilter
;
import
com.alibaba.fastjson.JSON
;
import
lombok.extern.slf4j.Slf4j
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
org.springframework.test.util.ReflectionTestUtils
;
import
javax.annotation.Resource
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 抽奖策略测试
* @create 2024-01-06 13:28
*/
@Slf4j
@RunWith
(
SpringRunner
.
class
)
@SpringBootTest
public
class
RaffleStrategyTest
{
@Resource
private
IRaffleStrategy
raffleStrategy
;
@Resource
private
RuleWeightLogicFilter
ruleWeightLogicFilter
;
@Before
public
void
setUp
()
{
ReflectionTestUtils
.
setField
(
ruleWeightLogicFilter
,
"userScore"
,
40500L
);
}
@Test
public
void
test_performRaffle
()
{
RaffleFactorEntity
raffleFactorEntity
=
RaffleFactorEntity
.
builder
()
.
userId
(
"xiaofuge"
)
.
strategyId
(
100001L
)
.
build
();
RaffleAwardEntity
raffleAwardEntity
=
raffleStrategy
.
performRaffle
(
raffleFactorEntity
);
log
.
info
(
"请求参数:{}"
,
JSON
.
toJSONString
(
raffleFactorEntity
));
log
.
info
(
"测试结果:{}"
,
JSON
.
toJSONString
(
raffleAwardEntity
));
}
@Test
public
void
test_performRaffle_blacklist
()
{
RaffleFactorEntity
raffleFactorEntity
=
RaffleFactorEntity
.
builder
()
.
userId
(
"user003"
)
// 黑名单用户 user001,user002,user003
.
strategyId
(
100001L
)
.
build
();
RaffleAwardEntity
raffleAwardEntity
=
raffleStrategy
.
performRaffle
(
raffleFactorEntity
);
log
.
info
(
"请求参数:{}"
,
JSON
.
toJSONString
(
raffleFactorEntity
));
log
.
info
(
"测试结果:{}"
,
JSON
.
toJSONString
(
raffleAwardEntity
));
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/AwardEntity.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.model.entity
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
/**
* @description: 策略结果实体
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity
* @DATE: 2024/4/12
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
AwardEntity
{
/** 用户ID */
private
String
userId
;
/** 奖品ID */
private
Integer
awardId
;
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleAwardEntity.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.model.entity
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
/**
* @description: 抽奖奖品实体
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity
* @DATE: 2024/4/12
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
RaffleAwardEntity
{
/**
* 策略Id
*/
private
Long
strategyId
;
/**
* 奖品ID
*/
private
Integer
awardId
;
/**
* 奖品对接标识 - 每一个都是一个对应的发奖策略
*/
private
String
awardKey
;
/**
* 奖品配置信息
*/
private
String
awardConfig
;
/**
* 奖品内容描述
*/
private
String
awardDesc
;
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RaffleFactorEntity.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.model.entity
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
/**
* @description: 抽奖因子实体
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity
* @DATE: 2024/4/12
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
RaffleFactorEntity
{
/** 用户ID */
private
String
userId
;
/** 策略ID */
private
Long
strategyId
;
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RuleActionEntity.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.model.entity
;
import
cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO
;
import
lombok.*
;
/**
* @description: 规则动作实体
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity
* @DATE: 2024/4/12
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public
class
RuleActionEntity
<
T
extends
RuleActionEntity
.
RaffleEntity
>
{
private
String
code
=
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
();
private
String
info
=
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
();
private
String
ruleModel
;
private
T
data
;
static
public
class
RaffleEntity
{
}
// 抽奖之前
@EqualsAndHashCode
(
callSuper
=
true
)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
static
public
class
RaffleBeforeEntity
extends
RaffleEntity
{
/**
* 策略ID
*/
private
Long
strategyId
;
/**
* 权重值Key;用于抽奖时可以选择权重抽奖。
*/
private
String
ruleWeightValueKey
;
/**
* 奖品ID;
*/
private
Integer
awardId
;
}
// 抽奖之中
static
public
class
RaffleCenterEntity
extends
RaffleEntity
{
}
// 抽奖之后
static
public
class
RaffleAfterEntity
extends
RaffleEntity
{
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/entity/RuleMatterEntity.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.model.entity
;
import
lombok.Data
;
/**
* @description: 规则物料实体对象,用于过滤规则的必要参数信息。
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity
* @DATE: 2024/4/12
*/
@Data
public
class
RuleMatterEntity
{
/** 用户ID */
private
String
userId
;
/** 策略ID */
private
Long
strategyId
;
/** 抽奖奖品ID【规则类型为策略,则不需要奖品ID】 */
private
Integer
awardId
;
/** 抽奖规则类型【rule_random - 随机值计算、rule_lock - 抽奖几次后解锁、rule_luck_award - 幸运奖(兜底奖品)】 */
private
String
ruleModel
;
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/model/valobj/RuleLogicCheckTypeVO.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.model.valobj
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
/**
* @description: 规则过滤校验类型值对象
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.model.entity.valobj
* @DATE: 2024/4/12
*/
@Getter
@AllArgsConstructor
public
enum
RuleLogicCheckTypeVO
{
ALLOW
(
"0000"
,
"放行;执行后续的流程,不受规则引擎影响"
),
TAKE_OVER
(
"0001"
,
"接管;后续的流程,受规则引擎执行结果影响"
),
;
private
final
String
code
;
private
final
String
info
;
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/repository/IStrategyRepository.java
浏览文件 @
070b7cdd
...
@@ -67,4 +67,13 @@ public interface IStrategyRepository {
...
@@ -67,4 +67,13 @@ public interface IStrategyRepository {
* @return
* @return
*/
*/
int
getRateRange
(
String
key
);
int
getRateRange
(
String
key
);
/**
* 查询策略规则值
* @param strategyId 策略id
* @param awardId 奖品id
* @param ruleModel 规则模型
* @return
*/
String
queryStrategyRuleValue
(
Long
strategyId
,
Integer
awardId
,
String
ruleModel
);
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/IRaffleStrategy.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service
;
import
cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity
;
/**
* @description: 抽奖策略接口
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service
* @DATE: 2024/4/11
*/
public
interface
IRaffleStrategy
{
/**
* 执行抽奖:用抽奖影子入参,执行抽奖计算,返回奖品信息
* @param raffleFactorEntity 抽奖因子实体
* @return 抽奖的奖品
*/
RaffleAwardEntity
performRaffle
(
RaffleFactorEntity
raffleFactorEntity
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/annotation/LogicStrategy.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service.annotation
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* @author Fuzhengwei bugstack.cn @小傅哥
* @description 策略自定义枚举
* @create 2023-12-31 11:29
*/
@Target
({
ElementType
.
TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
LogicStrategy
{
DefaultLogicFactory
.
LogicModel
logicMode
();
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/AbstractRaffleStrategy.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service.raffle
;
import
cn.bugstack.domain.strategy.model.entity.RaffleAwardEntity
;
import
cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.model.entity.StrategyEntity
;
import
cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.domain.strategy.service.IRaffleStrategy
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyDispatch
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
cn.bugstack.domain.strategy.service.rule.impl.RuleBackListLogicFilter
;
import
cn.bugstack.types.enums.ResponseCode
;
import
cn.bugstack.types.exception.AppException
;
import
com.alibaba.fastjson.JSON
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
/**
* @description:
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service.raffle
* @DATE: 2024/4/12
*/
@Slf4j
public
abstract
class
AbstractRaffleStrategy
implements
IRaffleStrategy
{
// 策略仓储服务 -> domain层像一个大厨,仓储层提供米面粮油
protected
IStrategyRepository
repository
;
// 策略调度服务 -> 只负责抽奖处理,通过新增接口的方式,隔离职责,不需要使用方关心或者调用抽奖的初始化
protected
IStrategyDispatch
strategyDispatch
;
public
AbstractRaffleStrategy
(
IStrategyRepository
repository
,
IStrategyDispatch
strategyDispatch
)
{
this
.
repository
=
repository
;
this
.
strategyDispatch
=
strategyDispatch
;
}
@Override
public
RaffleAwardEntity
performRaffle
(
RaffleFactorEntity
raffleFactorEntity
)
{
// 1. 参数校验
String
userId
=
raffleFactorEntity
.
getUserId
();
Long
strategyId
=
raffleFactorEntity
.
getStrategyId
();
if
(
null
==
strategyId
||
StringUtils
.
isBlank
(
userId
))
{
throw
new
AppException
(
ResponseCode
.
ILLEGAL_PARAMETER
.
getCode
(),
ResponseCode
.
ILLEGAL_PARAMETER
.
getInfo
());
}
// 2. 策略查询
StrategyEntity
strategy
=
repository
.
queryStrategyEntityByStrategyId
(
strategyId
)
;
// 3. 抽奖前 - 规则过滤
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
ruleActionEntity
=
this
.
doCheckRaffleBeforeLogic
(
RaffleFactorEntity
.
builder
()
.
userId
(
userId
)
.
strategyId
(
strategyId
)
.
build
(),
strategy
.
ruleModels
());
log
.
info
(
"ruleActionEntity:{}"
,
JSON
.
toJSONString
(
ruleActionEntity
));
if
(
RuleLogicCheckTypeVO
.
TAKE_OVER
.
getCode
().
equals
(
ruleActionEntity
.
getCode
()))
{
if
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
().
equals
(
ruleActionEntity
.
getRuleModel
()))
{
// 黑名单返回固定的奖品ID
return
RaffleAwardEntity
.
builder
()
.
awardId
(
ruleActionEntity
.
getData
().
getAwardId
())
.
build
();
}
else
if
(
DefaultLogicFactory
.
LogicModel
.
RULE_WIGHT
.
getCode
().
equals
(
ruleActionEntity
.
getRuleModel
()))
{
// 权重根据返回的信息进行抽奖
System
.
out
.
println
(
"权重抽奖"
);
RuleActionEntity
.
RaffleBeforeEntity
raffleBeforeEntity
=
ruleActionEntity
.
getData
();
String
ruleWeightValueKey
=
raffleBeforeEntity
.
getRuleWeightValueKey
();
Integer
awardId
=
strategyDispatch
.
getRandomAwardId
(
strategyId
,
ruleWeightValueKey
);
return
RaffleAwardEntity
.
builder
()
.
awardId
(
awardId
)
.
build
();
}
}
// 4. 默认抽奖流程
System
.
out
.
println
(
"默认抽奖"
);
Integer
awardId
=
strategyDispatch
.
getRandomAwardId
(
strategyId
);
return
RaffleAwardEntity
.
builder
()
.
awardId
(
awardId
)
.
build
();
}
protected
abstract
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
doCheckRaffleBeforeLogic
(
RaffleFactorEntity
factorEntity
,
String
...
logics
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/raffle/DefaultRaffleStrategy.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service.raffle
;
import
cn.bugstack.domain.strategy.model.entity.RaffleFactorEntity
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.model.entity.RuleMatterEntity
;
import
cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.domain.strategy.service.armory.IStrategyDispatch
;
import
cn.bugstack.domain.strategy.service.rule.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
com.alibaba.fastjson.JSON
;
import
com.sun.deploy.security.ruleset.RuleAction
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
import
javax.annotation.Resource
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
* @description:
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service.raffle
* @DATE: 2024/4/12
*/
@Slf4j
@Service
public
class
DefaultRaffleStrategy
extends
AbstractRaffleStrategy
{
@Resource
private
DefaultLogicFactory
logicFactory
;
public
DefaultRaffleStrategy
(
IStrategyRepository
repository
,
IStrategyDispatch
strategyDispatch
)
{
super
(
repository
,
strategyDispatch
);
}
@Override
protected
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
doCheckRaffleBeforeLogic
(
RaffleFactorEntity
raffleFactorEntity
,
String
...
logics
)
{
log
.
info
(
"raffleFactorEntity:{},logics:{}"
,
JSON
.
toJSONString
(
raffleFactorEntity
),
logics
);
Map
<
String
,
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>>
logicFilterGroup
=
logicFactory
.
openLogicFilter
();
// 黑名单规则优先过滤
String
ruleBackList
=
Arrays
.
stream
(
logics
)
.
filter
(
str
->
str
.
contains
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
()))
.
findFirst
()
.
orElse
(
null
);
if
(
StringUtils
.
isNotBlank
(
ruleBackList
))
{
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>
logicFilter
=
logicFilterGroup
.
get
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
());
RuleMatterEntity
ruleMatterEntity
=
new
RuleMatterEntity
();
ruleMatterEntity
.
setUserId
(
raffleFactorEntity
.
getUserId
());
ruleMatterEntity
.
setAwardId
(
ruleMatterEntity
.
getAwardId
());
ruleMatterEntity
.
setStrategyId
(
raffleFactorEntity
.
getStrategyId
());
ruleMatterEntity
.
setRuleModel
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
());
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
ruleActionEntity
=
logicFilter
.
filter
(
ruleMatterEntity
);
if
(!
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
().
equals
(
ruleActionEntity
.
getCode
()))
{
return
ruleActionEntity
;
}
}
// 顺序过滤剩余规则
List
<
String
>
ruleList
=
Arrays
.
stream
(
logics
)
.
filter
(
str
->
!
str
.
contains
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
()))
.
collect
(
Collectors
.
toList
());
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
ruleActionEntity
=
null
;
for
(
String
ruleModel
:
ruleList
)
{
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>
logicFilter
=
logicFilterGroup
.
get
(
ruleModel
);
RuleMatterEntity
ruleMatterEntity
=
new
RuleMatterEntity
();
ruleMatterEntity
.
setUserId
(
raffleFactorEntity
.
getUserId
());
// todo 数据不对
ruleMatterEntity
.
setAwardId
(
ruleMatterEntity
.
getAwardId
());
ruleMatterEntity
.
setStrategyId
(
raffleFactorEntity
.
getStrategyId
());
ruleMatterEntity
.
setRuleModel
(
ruleModel
);
ruleActionEntity
=
logicFilter
.
filter
(
ruleMatterEntity
);
log
.
info
(
"ruleActionEntity:{}"
,
JSON
.
toJSONString
(
ruleActionEntity
));
log
.
info
(
"抽奖前规则过滤 userId: {} ruleModel: {} code: {} info: {}"
,
raffleFactorEntity
.
getUserId
(),
ruleModel
,
ruleActionEntity
.
getCode
(),
ruleActionEntity
.
getInfo
());
if
(!
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
().
equals
(
ruleActionEntity
.
getCode
()))
{
return
ruleActionEntity
;
}
}
return
ruleActionEntity
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/ILogicFilter.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service.rule
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.model.entity.RuleMatterEntity
;
/**
* @description: 抽奖规则过滤接口
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule
* @DATE: 2024/4/12
*/
public
interface
ILogicFilter
<
T
extends
RuleActionEntity
.
RaffleEntity
>
{
RuleActionEntity
<
T
>
filter
(
RuleMatterEntity
ruleMatterEntity
);
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/factory/DefaultLogicFactory.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service.rule.factory
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.service.annotation.LogicStrategy
;
import
cn.bugstack.domain.strategy.service.rule.ILogicFilter
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* @description: 规则工厂
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule.factory
* @DATE: 2024/4/12
*/
@Service
public
class
DefaultLogicFactory
{
public
Map
<
String
,
ILogicFilter
<?>>
logicFilterMap
=
new
ConcurrentHashMap
<>();
public
DefaultLogicFactory
(
List
<
ILogicFilter
<?>>
logicFilters
)
{
logicFilters
.
forEach
(
logic
->
{
LogicStrategy
strategy
=
AnnotationUtils
.
findAnnotation
(
logic
.
getClass
(),
LogicStrategy
.
class
);
if
(
null
!=
strategy
)
{
logicFilterMap
.
put
(
strategy
.
logicMode
().
getCode
(),
logic
);
}
});
}
public
<
T
extends
RuleActionEntity
.
RaffleEntity
>
Map
<
String
,
ILogicFilter
<
T
>>
openLogicFilter
()
{
return
(
Map
<
String
,
ILogicFilter
<
T
>>)
(
Map
<?,
?>)
logicFilterMap
;
}
@Getter
@AllArgsConstructor
public
enum
LogicModel
{
RULE_WIGHT
(
"rule_weight"
,
"【抽奖前规则】根据抽奖权重返回可抽奖范围KEY"
),
RULE_BLACKLIST
(
"rule_blacklist"
,
"【抽奖前规则】黑名单规则过滤,命中黑名单则直接返回"
),
;
private
final
String
code
;
private
final
String
info
;
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/impl/RuleBackListLogicFilter.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service.rule.impl
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.model.entity.RuleMatterEntity
;
import
cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.domain.strategy.service.annotation.LogicStrategy
;
import
cn.bugstack.domain.strategy.service.rule.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
cn.bugstack.types.common.Constants
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
/**
* @description: [抽奖前规则]黑名单用户过滤规则
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule.impl
* @DATE: 2024/4/12
*/
@Slf4j
@Component
@LogicStrategy
(
logicMode
=
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
)
public
class
RuleBackListLogicFilter
implements
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>
{
@Resource
private
IStrategyRepository
repository
;
@Override
public
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
filter
(
RuleMatterEntity
ruleMatterEntity
)
{
log
.
info
(
"规则过滤-黑名单 userId:{} strategyId:{} ruleModel:{}"
,
ruleMatterEntity
.
getUserId
(),
ruleMatterEntity
.
getStrategyId
(),
ruleMatterEntity
.
getRuleModel
());
String
userId
=
ruleMatterEntity
.
getUserId
();
// 100:user001,user002,user003
// 查询规则值配置
String
ruleValue
=
repository
.
queryStrategyRuleValue
(
ruleMatterEntity
.
getStrategyId
(),
ruleMatterEntity
.
getAwardId
(),
ruleMatterEntity
.
getRuleModel
());
String
[]
splitRuleValue
=
ruleValue
.
split
(
Constants
.
COLON
);
//
Integer
awardId
=
Integer
.
parseInt
(
splitRuleValue
[
0
]);
// 过滤其他规则
String
[]
userBlackIds
=
splitRuleValue
[
1
].
split
(
Constants
.
SPLIT
);
for
(
String
userBlackId
:
userBlackIds
)
{
if
(
userId
.
equals
(
userBlackId
))
{
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
ruleModel
(
DefaultLogicFactory
.
LogicModel
.
RULE_BLACKLIST
.
getCode
())
.
data
(
RuleActionEntity
.
RaffleBeforeEntity
.
builder
()
.
strategyId
(
ruleMatterEntity
.
getStrategyId
())
.
awardId
(
awardId
)
.
build
())
.
code
(
RuleLogicCheckTypeVO
.
TAKE_OVER
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
TAKE_OVER
.
getInfo
())
.
build
();
}
}
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
.
build
();
}
}
xfg-frame-archetype-lite-domain/src/main/java/cn/bugstack/domain/strategy/service/rule/impl/RuleWeightLogicFilter.java
0 → 100644
浏览文件 @
070b7cdd
package
cn.bugstack.domain.strategy.service.rule.impl
;
import
cn.bugstack.domain.strategy.model.entity.RuleActionEntity
;
import
cn.bugstack.domain.strategy.model.entity.RuleMatterEntity
;
import
cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO
;
import
cn.bugstack.domain.strategy.repository.IStrategyRepository
;
import
cn.bugstack.domain.strategy.service.annotation.LogicStrategy
;
import
cn.bugstack.domain.strategy.service.rule.ILogicFilter
;
import
cn.bugstack.domain.strategy.service.rule.factory.DefaultLogicFactory
;
import
cn.bugstack.types.common.Constants
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
java.util.*
;
/**
* @description: [抽奖前规则] 根据抽奖鉴权重返可抽奖范围key
* @author: hdr
* @PACKAGE_NAME: cn.bugstack.domain.strategy.service.rule.impl
* @DATE: 2024/4/12
*/
@Slf4j
@Component
@LogicStrategy
(
logicMode
=
DefaultLogicFactory
.
LogicModel
.
RULE_WIGHT
)
public
class
RuleWeightLogicFilter
implements
ILogicFilter
<
RuleActionEntity
.
RaffleBeforeEntity
>
{
@Resource
private
IStrategyRepository
repository
;
public
Long
userScore
=
4500L
;
/**
* 1. 权重规则格式;4000:102,103,104,105 5000:102,103,104,105,106,107 6000:102,103,104,105,106,107,108,109
* 2. 解析数据格式;判断哪个范围符合用户的特定抽奖范围
* @param ruleMatterEntity
* @return
*/
@Override
public
RuleActionEntity
<
RuleActionEntity
.
RaffleBeforeEntity
>
filter
(
RuleMatterEntity
ruleMatterEntity
)
{
log
.
info
(
"规则过滤-权重范围 userId:{} strategyId:{} ruleModel:{}"
,
ruleMatterEntity
.
getUserId
(),
ruleMatterEntity
.
getStrategyId
(),
ruleMatterEntity
.
getRuleModel
());
String
userId
=
ruleMatterEntity
.
getUserId
();
Long
strategyId
=
ruleMatterEntity
.
getStrategyId
();
String
ruleValue
=
repository
.
queryStrategyRuleValue
(
ruleMatterEntity
.
getStrategyId
(),
ruleMatterEntity
.
getAwardId
(),
ruleMatterEntity
.
getRuleModel
());
// 1. 根据用户ID查询用户抽奖消耗的积分值,本章节我们先写死为固定的值。后续需要从数据库中查询。
Map
<
Long
,
String
>
analyticalValueGroup
=
getAnalyticalValue
(
ruleValue
);
if
(
null
==
analyticalValueGroup
||
analyticalValueGroup
.
isEmpty
())
{
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
.
build
();
}
// 2. 转换Keys值,并默认排序
List
<
Long
>
analyticalSortedKeys
=
new
ArrayList
<>(
analyticalValueGroup
.
keySet
());
Collections
.
sort
(
analyticalSortedKeys
);
// 3. 找出最小符合的值,也就是【4500 积分,能找到 4000:102,103,104,105】、【5000 积分,能找到 5000:102,103,104,105,106,107】
Long
nextValue
=
analyticalSortedKeys
.
stream
()
.
filter
(
key
->
userScore
>=
key
)
.
findFirst
()
.
orElse
(
null
);
if
(
null
!=
nextValue
)
{
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
data
(
RuleActionEntity
.
RaffleBeforeEntity
.
builder
()
.
strategyId
(
strategyId
)
.
ruleWeightValueKey
(
analyticalValueGroup
.
get
(
nextValue
))
.
build
())
.
ruleModel
(
DefaultLogicFactory
.
LogicModel
.
RULE_WIGHT
.
getCode
())
.
code
(
RuleLogicCheckTypeVO
.
TAKE_OVER
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
TAKE_OVER
.
getInfo
())
.
build
();
}
return
RuleActionEntity
.<
RuleActionEntity
.
RaffleBeforeEntity
>
builder
()
.
code
(
RuleLogicCheckTypeVO
.
ALLOW
.
getCode
())
.
info
(
RuleLogicCheckTypeVO
.
ALLOW
.
getInfo
())
.
build
();
}
private
Map
<
Long
,
String
>
getAnalyticalValue
(
String
ruleValue
)
{
String
[]
ruleValueGroups
=
ruleValue
.
split
(
Constants
.
SPACE
);
Map
<
Long
,
String
>
ruleValueMap
=
new
HashMap
<>();
for
(
String
ruleValueGroup
:
ruleValueGroups
)
{
// 检查驶入是否为空
if
(
ruleValueGroup
==
null
||
ruleValueGroup
.
isEmpty
())
{
return
ruleValueMap
;
}
// 分割字符串以获取键和值
String
[]
parts
=
ruleValueGroup
.
split
(
Constants
.
COLON
);
if
(
parts
.
length
<
2
)
{
throw
new
IllegalArgumentException
(
"rule_weight rule_rule invalid input format"
+
ruleValueGroup
);
}
ruleValueMap
.
put
(
Long
.
parseLong
(
parts
[
0
]),
ruleValueGroup
);
}
return
ruleValueMap
;
}
}
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/dao/IStrategyRuleDao.java
浏览文件 @
070b7cdd
...
@@ -21,4 +21,11 @@ public interface IStrategyRuleDao {
...
@@ -21,4 +21,11 @@ public interface IStrategyRuleDao {
* @return
* @return
*/
*/
StrategyRule
queryStrategyRule
(
StrategyRule
strategyRuleReq
);
StrategyRule
queryStrategyRule
(
StrategyRule
strategyRuleReq
);
/**
* 查询规则值
* @param strategyRule
* @return
*/
String
queryStrategyRuleValue
(
StrategyRule
strategyRule
);
}
}
xfg-frame-archetype-lite-infrastructure/src/main/java/cn/bugstack/infrastructure/persistent/repository/StrategyRepository.java
浏览文件 @
070b7cdd
...
@@ -143,4 +143,13 @@ public class StrategyRepository implements IStrategyRepository {
...
@@ -143,4 +143,13 @@ public class StrategyRepository implements IStrategyRepository {
return
redisService
.
getValue
(
Constants
.
RedisKey
.
STRATEGY_RATE_RANGE_KEY
+
key
);
return
redisService
.
getValue
(
Constants
.
RedisKey
.
STRATEGY_RATE_RANGE_KEY
+
key
);
}
}
@Override
public
String
queryStrategyRuleValue
(
Long
strategyId
,
Integer
awardId
,
String
ruleModel
)
{
StrategyRule
strategyRule
=
new
StrategyRule
();
strategyRule
.
setStrategyId
(
strategyId
);
strategyRule
.
setRuleModel
(
ruleModel
);
strategyRule
.
setAwardId
(
awardId
);
return
strategyRuleDao
.
queryStrategyRuleValue
(
strategyRule
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录