1.规则引擎特点
- 随着业务的发展规则增加
- 随着业务的复杂规则复杂
- 随着业务的发展规则变化不会非常大(变化也存在局限性)
实现的解决的问题:高复用、高灵活、可扩展、基础方法更加简单,实现误区就为了高灵活性牺牲接口的性能。
DEMO 代码
规则配置
建立 config package目录,存储每个规则对应的配置信息,实现灵活性
@Data
public class BlackFilterConfig extends BaseFilterConfig {
private List<Long> blackItemIdList;
}
规则实现
首先设置规则的执行器
public abstract class AbstractStrategyFilter<T> {
/**
* 执行用户维度产品 filter
*
* @param SourceEnum
* @param Object
* @param itemInfoList
*/
public void doFilter(SourceEnum sourceEnum, Object vo, List<Object> itemInfoList) {
/**
*获取配置
*/
T configBySource = getConfigBySource(sourceEnum, itemInfoList);
/**
* 过滤参数收集
*/
List<Long> blackItemIdList = collectBlackItemId(configBySource, userInfoVO);
log.info("[AbstractStrategyFilter-doFilter] filterName:{},blackItemId:{}", this.getClass().getSimpleName()
, JSON.toJSONString(blackItemIdList));
if (CollectionUtils.isEmpty(blackItemIdList)) {
return;
}
/**
* 执行过滤
*/
itemInfoList.removeIf(i -> blackItemIdList.contains(i.getItemId()));
}
/**
* 按照配置获取config
*
* @param positionEnum
* @return
*/
protected abstract T getConfigBySource(SourceEnum source, List<Object> itemInfoList);
/**
* 收集待过滤集合
*
* @param config
* @return
*/
protected abstract List<Long> collectFilterItemId(T config, Object vo);
继承规则执行器实现每个规则,建立 rule package 添加规则代码
public class BlackFilter extends AbstractStrategyFilter<BlackFilterConfig> {
@Override
protected BlackFilterConfig getConfigBySource(SourceEnum positionEnum, List<Object> itemInfoList) {
/**自己实现逻辑,组装配置信息**/
return BlackFilterConfig.builder().blackItemIdList(null).build();
}
/**
*按照 config 配置实现具体的代码逻辑,收集待过滤的集合
*/
@Override
protected List<Long> collectBlackItemId(BlackFilterConfig config, UserInfoVO userInfoVO) {
Set<Long> blackList = new HashSet<Long>();
if (null != config && !CollectionUtils.isEmpty(config.getBlackItemIdList())) {
blackList.addAll(config.getBlackItemIdList());
}
return new ArrayList<>(blackList);
}
}
外观类执行
设置全量规则之后,通过 chooseFilter 的入参 source 执行筛选逻辑,选择需要的规则去执行,针对规则有配置定制的情况可以使用每个规则的 config 配置信息,然后再执行的时候直接使用即可。
@Service
public class FilterStrategyExecutorImpl implements FilterStrategyExecutor {
/**
* 执行器
*
* @param itemInfoList
* @param userInfoVO
*/
@Override
public void executor(SourceEnum positionEnum, List<Object> itemInfoList, Object userInfoVO) {
List<AbstractStrategyFilter> filters = chooseFilters(positionEnum);
if (CollectionUtils.isEmpty(filters)) {
log.info("[FilterStrategyActuator-executor] filterStrategy end empty");
return;
}
for (AbstractStrategyFilter vo : filters) {
try {
if (CollectionUtils.isEmpty(itemInfoList)) {
log.info("[FilterStrategyActuator-executor] end data filter2Null,currentFilter:{}", vo.getClass().getSimpleName());
return;
}
vo.doFilter(positionEnum, userInfoVO, itemInfoList);
} catch (Exception e) {
log.error("[FilterStrategyActuator-executor]error,currentFilter:{}", vo.getClass().getSimpleName(),e);
}
}
}
/**
* 设置所有规则
*
* @return
*/
private List<AbstractStrategyFilter> getFilters() {
List<AbstractStrategyFilter> filters = new ArrayList<>();
filters.add(new BlackFilter());
filters.add(new XXX());
return filters;
}
/**
* 按照入参 sourceEnum 筛选规则
*
* @param positionEnum
* @return
*/
private List<AbstractStrategyFilter> chooseFilters(SourceEnum positionEnum) {
log.info("[FilterStrategyExecutor-chooseFilters] filter start");
List<AbstractStrategyFilter> filters = getFilters();
ConfigCenterConfigureEnum enumConfig = ConfigCenterConfigureEnum.POSITION_FILTER_CONFIG;
String positionName = String.format(enumConfig.getKey(), positionEnum.getName());
String ruleNameArrStr = ConfigHolder.getProperties(ConfigCenterConstants.NAMESPACE_SWITCH, positionName, enumConfig.getValue());
List<String> filterArray = Arrays.asList(ruleNameArrStr.split(","));
filters.removeIf(f -> !filterArray.contains(f.getClass().getSimpleName()));
log.info("[FilterStrategyExecutor-chooseFilters] filter end size:{}", filters.size());
return filters;
}
}
总结
此处的代码有几处可以按照需求进行优化
- getFilters 方法可以通过数据库的方式选择需要进行 new ,减少无效的内存使用。
- 每个规则的配置信息需要没有和 filter 绑定在一起,现在 new BlackFilter 的时候没有设置 config 入参(额是打工人)
- config 信息最好和规则在一起通过数据库全量获取到,然后分发到每个规则中,减少配置信息的获取成本。
说明:如需要添加其他规则,直接添加继承抽象类实现代码,然后在getFilters 的时候添加到规则 List 中。