1.规则引擎特点

  1. 随着业务的发展规则增加
  2. 随着业务的复杂规则复杂
  3. 随着业务的发展规则变化不会非常大(变化也存在局限性)

实现的解决的问题:高复用、高灵活、可扩展、基础方法更加简单,实现误区就为了高灵活性牺牲接口的性能。

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;
    }
}

总结

此处的代码有几处可以按照需求进行优化

  1. getFilters 方法可以通过数据库的方式选择需要进行 new ,减少无效的内存使用。
  2. 每个规则的配置信息需要没有和 filter 绑定在一起,现在 new BlackFilter 的时候没有设置 config 入参(额是打工人)
  3. config 信息最好和规则在一起通过数据库全量获取到,然后分发到每个规则中,减少配置信息的获取成本。

说明:如需要添加其他规则,直接添加继承抽象类实现代码,然后在getFilters 的时候添加到规则 List 中。