基于java实现规则引擎设计思路

背景

去年底换了公司,目前在做HR招聘系统,产品要求:管理端手动配置发布招聘要求(支持多个招聘条件AND与OR关系编排);当C端用户报名该职位时,系统执行该规则,返回报名成功或失败。根据技术调研,采用db存规则json串。然后报名时,执行该规则的方法。

前端样式

在这里插入图片描述
招聘岗位的多个规则关系是OR关系;同1个条件点击+号,可增加多个规则,是AND条件

代码入口

在这里插入图片描述
比如上述单元测试的场景:招java开发岗,要求:满足本科+35岁以下或本科+P7以上即可。
执行单测:
通过日志就能清晰的分析出,岗位配了什么规则,各规则的执行结果是什么
在这里插入图片描述

代码设计

类图

通过工厂+策略的设计模式,实现该规则,符合开闭原则,方便后续业务规则扩充,代码扩展
在这里插入图片描述

代码介绍

核心接口:InternalPositionRule 定义了规则执行的统一方法。
抽象类:AbstractPositionRule 提供了通用的比较和告警逻辑。
具体规则类:如 AgeRule、SexRule 等,继承自 AbstractPositionRule。
规则包装类:RuleWrapper 用于封装规则信息并动态创建规则实例。
规则组和规则集:RuleGroup 和 RuleSet 用于组织规则的逻辑关系(AND 和 OR)。
规则上下文:PositionRuleContext 是规则引擎的统一入口。
规则工厂:PositionRuleFactory 用于动态创建规则实例。
员工类:Employee 包含员工的基本信息,用于规则匹配。

核心代码

以下是脱敏后的核心代码
InternalPositionRule 岗位规则 接口 最顶层抽象,制定模版方法

* +-----------------------------------+
 * |  InternalPositionRule (接口)       |
 * |-----------------------------------|
 * |  + execute(Employee emp): boolean |
 * +-----------------------------------+
 *                 ^
 *                 |
 *                 |
 * +-----------------------------------+
 * |  AbstractPositionRule<T> (抽象类)  |
 * |-----------------------------------|
 * |  + compare(String, T, T): boolean |
 * |-----------------------------------|
 * |  - ruleValue: String              |
 * |  - forceFlag: String              |
 * |  - compareSymbol: String          |
 * +-----------------------------------+
 *                 ^
 *                 |
 *                 |
 * +-----------------------------------+
 * |  AgeRule                           |
 * |-----------------------------------|
 * |  + execute(Employee emp): boolean |
 * +-----------------------------------+
 **/
public interface InternalPositionRule {
   
   

    /**
     * 执行岗位条件规则
     *
     * @param emp 员工信息
     * @return true/false
     */
    boolean execute(Employee emp);

AbstractPositionRule 岗位规则 抽象类:业务上再扩展规则,继承该类即可

@Slf4j
@Component
public abstract class AbstractPositionRule<T extends Comparable<? super T>> implements InternalPositionRule {
   
   

    /**
     * 执行岗位条件规则
     *
     * @param emp 员工信息
     * @return
     */
    public abstract boolean execute(Employee emp);

    /**
     * 比较方法
     *
     * @param compareSymbol  比较符号
     * @param actualValue    实际值
     * @param thresholdValue 设定阈值
     * @return
     */
    public boolean compare(String compareSymbol, T actualValue, T thresholdValue) {
   
   
        boolean result;
        log.info("===比较开始,比较符号【{}】,配置阈值【{}】,实际值【{}】===", compareSymbol, thresholdValue, actualValue);
        //等于
        if (SymbolConstant.EQ.equalsIgnoreCase(compareSymbol)) {
   
   
            result = CompareUtil.equals(actualValue, thresholdValue);
            //大于
        } else if (SymbolConstant.GT.equalsIgnoreCase(compareSymbol)) {
   
   
            result = CompareUtil.gt(actualValue, thresholdValue);
            //小于
        } else if (SymbolConstant.LT.equalsIgnoreCase(compareSymbol)) {
   
   
            result = CompareUtil.lt(actualValue, thresholdValue);
            //大于等于
        } else if (SymbolConstant.GE.equalsIgnoreCase(compareSymbol)) {
   
   
            result = CompareUtil.ge(actualValue, thresholdValue);
            //小于等于
        } else if (SymbolConstant.LE.equalsIgnoreCase(compareSymbol)) {
   
   
            result = CompareUtil.le(actualValue, thresholdValue);
        } else {
   
   
            log.error(StrUtil.join("当前类型:", compareSymbol, InternalErrorCode.TYPE_UNSUPPORTED_ERROR.getMsg()));
            throw new ServiceException(InternalErrorCode.TYPE_UNSUPPORTED_ERROR);
        }
        log.info("==比较结束,结果【{}】===", result);
        return result;
    }

    /**
     * TODO 产品给出告警文案?怎么触达用户?是否持久化落库?
     * 告警逻辑:要求如果规则配置了告警,即使匹配失败,也允许通过,并返回告警文案
     *
     * @param compareResult 实际匹配结果
     * @param forceFlag     禁止或告警
     * @param ruleTypeEnum  规则类型
     * @return
     */
    public Optional<String
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值