最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Java實現(xiàn)的簡易規(guī)則引擎

 更新時間:2026年02月07日 09:51:11   作者:碼頭整點薯條  
這篇文章主要介紹了基于Java實現(xiàn)的簡易規(guī)則引擎,支持動態(tài)選擇表和字段形成各種判定規(guī)則,并進行不同組合,通過數(shù)據(jù)模型設(shè)計、樹形結(jié)構(gòu)設(shè)計和遞歸處理機制,實現(xiàn)了規(guī)則的判斷和組合,感興趣的可以了解一下

一、背景介紹

這段時間工作上,需要開發(fā)一個功能,可以動態(tài)選擇表和字段形成一條條規(guī)則,然后規(guī)則又可以進行不通的組合,比如三條中至少滿足一條并且滿足另外一條這種刁鉆的規(guī)則條件,具體功能描述可以看圖。當時還真是為了實現(xiàn)這個功能考慮到頭大,他難點在于既要實現(xiàn)規(guī)則的判斷,又要滿足下面條件的二次判斷,好在也在同事的幫助下想出了思路,這里和大家分享下,后續(xù)類似地方都可以參考這個思路。

二、核心思路分析

1. 問題分析

在系統(tǒng)中,我們需要實現(xiàn)以下功能:

  • 支持靈活配置各種判定規(guī)則
  • 支持規(guī)則之間的邏輯組合(AND/OR)
  • 支持規(guī)則組的概念(設(shè)置最小 / 最大滿足數(shù)量)
  • 支持可視化配置規(guī)則樹

2. 設(shè)計思路

為了解決這些問題,我們采用了以下設(shè)計思路:

(1)數(shù)據(jù)模型設(shè)計

將規(guī)則系統(tǒng)分為兩個核心部分:

  • 規(guī)則定義:存儲具體的規(guī)則內(nèi)容(如血壓 > 140mmHg)
  • 規(guī)則配置:存儲規(guī)則之間的邏輯關(guān)系(如規(guī)則 A AND 規(guī)則 B)

(2)樹形結(jié)構(gòu)設(shè)計

使用樹形結(jié)構(gòu)來表示規(guī)則之間的邏輯關(guān)系,支持三種節(jié)點類型:

  • RULE:具體的規(guī)則節(jié)點
  • OPERATOR:邏輯運算符節(jié)點(AND/OR)
  • GROUP:規(guī)則組節(jié)點

(3)遞歸處理機制

使用遞歸算法來處理樹形結(jié)構(gòu),實現(xiàn)規(guī)則樹的轉(zhuǎn)換和解析。

三、核心代碼講解

1. 數(shù)據(jù)模型定義

(1)規(guī)則定義表(MonRuleDefinitions)

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("MON_RULE_DEFINITIONS")
@ApiModel(value = "MonRuleDefinitions對象", description = "判定規(guī)則定義表")
public class MonRuleDefinitions extends Model<MonRuleDefinitions> {

    @ApiModelProperty(value = "主鍵")
    @TableId(value = "ID", type = IdType.ASSIGN_ID)
    private String id;

    @ApiModelProperty(value = "規(guī)則組id")
    @TableField("RULE_GROUP_ID")
    private String ruleGroupId;

    @ApiModelProperty(value = "來源字典編碼【字典】;table_name")
    @TableField("FROM_DICT_CODE")
    private String fromDictCode;

    @ApiModelProperty(value = "具體字段編碼")
    @TableField("SPECIFIC_FIELD_CODE")
    private String specificFieldCode;

    @ApiModelProperty(value = "匹配值代碼【字典】;more_range")
    @TableField("MATCH_TYPE_CODE")
    private String matchTypeCode;

    @ApiModelProperty(value = "指標值")
    @TableField("ITEM_VALUE")
    private String itemValue;

    // ... 其他字段
}

代碼分析

  • 使用 MyBatis-Plus 的注解來映射數(shù)據(jù)庫表
  • 每個規(guī)則定義包含來源、字段、匹配類型、指標值等信息
  • 支持多種匹配類型(如大于、小于、等于)

(2)規(guī)則配置表(MonBaseRuleConfig)

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("MON_RULE_CONFIG")
@ApiModel(value = "MonBaseRuleConfig對象", description = "判定規(guī)則配置表")
public class MonBaseRuleConfig extends Model<MonBaseRuleConfig> {

    @ApiModelProperty(value = "主鍵")
    @TableId(value = "ID", type = IdType.ASSIGN_ID)
    private String id;

    @ApiModelProperty(value = "規(guī)則類型 1-疾病分級 2-患者管理 3-質(zhì)控")
    @TableField("RULE_TYPE")
    private String ruleType;

    @ApiModelProperty(value = "規(guī)則組id")
    @TableField("RULE_GROUP_ID")
    private String ruleGroupId;

    @ApiModelProperty(value = "父節(jié)點ID,用于構(gòu)建樹結(jié)構(gòu)")
    @TableField("PARENT_NODE_ID")
    private String parentNodeId;

    @ApiModelProperty(value = "節(jié)點類型(RULE、OPERATOR、GROUP)")
    @TableField("NODE_TYPE")
    private String nodeType;

    @ApiModelProperty(value = "邏輯運算符(AND、OR);more_range")
    @TableField("OPERATOR")
    private String operator;

    @ApiModelProperty(value = "如果節(jié)點是規(guī)則,則關(guān)聯(lián)規(guī)則ID")
    @TableField("RULE_ID")
    private String ruleId;

    @ApiModelProperty(value = "對于GROUP類型,最少滿足的規(guī)則數(shù)量;item_result_unit_code")
    @TableField("MIN_COUNT")
    private String minCount;

    @ApiModelProperty(value = "對于GROUP類型,最多滿足的規(guī)則數(shù)量")
    @TableField("MAX_COUNT")
    private String maxCount;

    // ... 其他字段
}

代碼分析

  • 支持三種節(jié)點類型:RULE、OPERATOR、GROUP
  • 使用 parentNodeId 來構(gòu)建樹形結(jié)構(gòu)
  • GROUP 類型支持設(shè)置最小 / 最大滿足數(shù)量

2. 規(guī)則節(jié)點工具類(RuleNodeUtil)

(1)遞歸轉(zhuǎn)換規(guī)則節(jié)點

public static void convertAndCollectNodes(RuleNodeDTO currentNode, String ruleGroupId,
                                          String parentNodeId, List<MonBaseRuleConfig> allNodes) {

    if ("RULE".equals(currentNode.getNodeType())&¤tNode.getRuleId() == null) {
        throw new BaseException(998,"規(guī)則節(jié)點缺少規(guī)則ID");
    }

    // 轉(zhuǎn)換當前DTO為數(shù)據(jù)庫實體
    MonBaseRuleConfig dbNode = new MonBaseRuleConfig();
    BeanUtil.copyProperties(currentNode, dbNode);
    dbNode.setRuleGroupId(ruleGroupId);
    
    // 特殊處理GROUP類型
    if ("GROUP".equals(currentNode.getNodeType())) {
        dbNode.setRuleId(String.join(",",(List<String>) currentNode.getRuleId()));
        if ("min".equals(currentNode.getCountType())){
            dbNode.setMinCount(currentNode.getCount());
            dbNode.setMaxCount("");
        }else {
            dbNode.setMaxCount(currentNode.getCount());
            dbNode.setMinCount("");
        }
    }
    
    allNodes.add(dbNode);

    // 遞歸處理子節(jié)點
    if (!CollectionUtils.isEmpty(currentNode.getChildren())) {
        for (RuleNodeDTO child : currentNode.getChildren()) {
            convertAndCollectNodes(child, ruleGroupId, currentNode.getId(), allNodes);
        }
    }
}

代碼分析

  • 遞歸處理規(guī)則樹,將前端傳遞的 DTO 轉(zhuǎn)換為數(shù)據(jù)庫實體
  • 特殊處理 GROUP 類型,支持設(shè)置最小 / 最大滿足數(shù)量
  • 驗證規(guī)則節(jié)點是否缺少規(guī)則 ID

(2)構(gòu)建規(guī)則樹

public static RuleNodeDTO buildNode(MonBaseRuleConfig currentNode, Map<String, List<MonBaseRuleConfig>> parentMap) {
    // 轉(zhuǎn)換為DTO
    RuleNodeDTO nodeDTO = BeanUtil.copyProperties(currentNode,RuleNodeDTO.class);
    
    // 獲取當前節(jié)點的子節(jié)點列表
    List<MonBaseRuleConfig> children = parentMap.getOrDefault(currentNode.getId(), new ArrayList<>());

    // 遞歸構(gòu)建子節(jié)點
    List<RuleNodeDTO> childDTOs = children.stream()
            .map(child -> buildNode(child, parentMap))
            .collect(Collectors.toList());

    // GROUP節(jié)點特殊處理
    if ("GROUP".equals(currentNode.getNodeType())) {
        if (!childDTOs.isEmpty()) {
            List<Object> ruleIds = childDTOs.stream().map(RuleNodeDTO::getRuleId).collect(Collectors.toList());
            RuleNodeDTO ruleNodeDTO = childDTOs.get(0);
            ruleNodeDTO.setRuleId(ruleIds);
            nodeDTO.setChildren(Collections.singletonList(ruleNodeDTO));
        }else {
            nodeDTO.setChildren(childDTOs);
        }
    } else {
        // 非GROUP節(jié)點保留完整嵌套結(jié)構(gòu)
        nodeDTO.setChildren(childDTOs);
    }

    return nodeDTO;
}

代碼分析

  • 遞歸構(gòu)建規(guī)則樹,將數(shù)據(jù)庫實體轉(zhuǎn)換為前端需要的 DTO
  • 特殊處理 GROUP 類型,合并子節(jié)點的規(guī)則 ID
  • 保留完整的嵌套結(jié)構(gòu),方便前端展示

3. 規(guī)則配置服務(wù)實現(xiàn)(MonBaseRuleConfigServiceImpl)

(1)保存規(guī)則節(jié)點

public Integer saveNode(List<RuleNodeDTO> judgeGroup, String ruleGroupId, List<MonRuleDefinitions> ruleDefinitions) {
    if (CollectionUtils.isEmpty(judgeGroup)) {
        return 0;
    }
    
    // 收集所有轉(zhuǎn)換后的數(shù)據(jù)庫實體
    List<MonBaseRuleConfig> allNodes = new ArrayList<>();
    
    // 處理頂級節(jié)點(遞歸處理所有子節(jié)點)
    for (RuleNodeDTO rootNode : judgeGroup) {
        RuleNodeUtil.convertAndCollectNodes(rootNode, ruleGroupId, null, allNodes);
    }
    
    // 批量插入數(shù)據(jù)庫
    if (!CollectionUtils.isEmpty(allNodes)) {
        // 刪除舊的規(guī)則配置
        List<MonBaseRuleConfig> list = this.lambdaQuery()
                .eq(MonBaseRuleConfig::getRuleGroupId, ruleGroupId)
                .list();
        list.removeIf(judge ->allNodes.stream()
                .map(MonBaseRuleConfig::getId).collect(Collectors.toList()).contains(judge.getId()));
        List<String> monConfigDel = list.stream().map(MonBaseRuleConfig::getId).collect(Collectors.toList());
        this.removeByIds(monConfigDel);
        
        // 保存新的規(guī)則配置
        this.saveOrUpdateBatch(allNodes);
    }
    
    return allNodes.size();
}

代碼分析

  • 批量保存規(guī)則節(jié)點,支持新增和更新
  • 先刪除舊的規(guī)則配置,再保存新的規(guī)則配置
  • 支持規(guī)則組的概念,方便管理多個規(guī)則

四、使用場景

1. 疾病分級判定

高血壓分級 = (收縮壓 > 140mmHg OR 舒張壓 > 90mmHg) AND 年齡 > 65歲

2. 患者管理規(guī)則

高?;颊?= (糖尿病 AND 血壓 > 130/80mmHg) OR (冠心病 AND 血脂異常)

3. 醫(yī)療質(zhì)量控制

質(zhì)控合格 = (病歷書寫完整率 > 95%) AND (隨訪及時率 > 90%) AND (患者滿意度 > 85%)

五、總結(jié)

通過以上分析,我們可以看到這套規(guī)則引擎實現(xiàn)方案具有以下特點:

  1. 靈活性:支持任意復(fù)雜的規(guī)則組合
  2. 可擴展性:方便添加新的規(guī)則類型和邏輯
  3. 可視化:支持前端可視化配置規(guī)則樹
  4. 復(fù)用性:規(guī)則可以被多個規(guī)則組復(fù)用

在實際應(yīng)用中,我們可以根據(jù)具體業(yè)務(wù)需求,靈活配置各種判定規(guī)則,提高系統(tǒng)的靈活性和可維護性。

六、優(yōu)化建議

  1. 性能優(yōu)化:遞歸處理在規(guī)則樹層級較深時可能存在性能問題,可以考慮使用迭代方式替代遞歸
  2. 事務(wù)管理:在批量保存規(guī)則節(jié)點時,建議添加事務(wù)管理,確保數(shù)據(jù)一致性
  3. 緩存機制:對于頻繁使用的規(guī)則配置,可以添加緩存機制,減少數(shù)據(jù)庫查詢
  4. 規(guī)則驗證:在保存規(guī)則前添加更嚴格的驗證邏輯,確保規(guī)則配置的合法性
// 優(yōu)化建議:添加事務(wù)管理
@Transactional(rollbackFor = Exception.class)
public Integer saveNode(List<RuleNodeDTO> judgeGroup, String ruleGroupId, List<MonRuleDefinitions> ruleDefinitions) {
    // ... 原有代碼
}

通過以上優(yōu)化,可以進一步提高規(guī)則引擎的性能和可靠性。

到此這篇關(guān)于基于Java實現(xiàn)的簡易規(guī)則引擎的文章就介紹到這了,更多相關(guān)Java 規(guī)則引擎內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何解決LocalDateTime傳值JSON格式化問題

    如何解決LocalDateTime傳值JSON格式化問題

    這篇文章主要介紹了如何解決LocalDateTime傳值JSON格式化問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Spring連接Mysql數(shù)據(jù)庫全過程

    Spring連接Mysql數(shù)據(jù)庫全過程

    這篇文章主要介紹了Spring連接Mysql數(shù)據(jù)庫全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 簡單了解SpringBoot HATEOAS使用方法

    簡單了解SpringBoot HATEOAS使用方法

    這篇文章主要介紹了簡單了解SpringBoot HATEOAS使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • Java判斷范圍型的數(shù)據(jù)是否存在重疊的方法

    Java判斷范圍型的數(shù)據(jù)是否存在重疊的方法

    遇到了個問題,同一天可以輸入多個時間段,但是每個時間段的時間不能出現(xiàn)重疊,這不就是判斷數(shù)據(jù)返回是否有重疊的變種嗎,所以本文給大家介紹了Java判斷范圍型的數(shù)據(jù)是否存在重疊的方法,需要的朋友可以參考下
    2024-07-07
  • springboot如何實現(xiàn)異步響應(yīng)請求(前端請求超時的問題解決)

    springboot如何實現(xiàn)異步響應(yīng)請求(前端請求超時的問題解決)

    這篇文章主要給大家介紹了關(guān)于springboot如何實現(xiàn)異步響應(yīng)請求(前端請求超時的問題解決)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,對大家學習或者使用springboot具有一定的參考學習價值,需要的朋友可以參考下
    2023-01-01
  • 基于XML配置Spring的自動裝配過程解析

    基于XML配置Spring的自動裝配過程解析

    這篇文章主要介紹了基于XML配置Spring的自動裝配過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • SpringBoot actuator 健康檢查不通過的解決方案

    SpringBoot actuator 健康檢查不通過的解決方案

    這篇文章主要介紹了SpringBoot actuator 健康檢查不通過的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java線程池隊列PriorityBlockingQueue和SynchronousQueue詳解

    Java線程池隊列PriorityBlockingQueue和SynchronousQueue詳解

    這篇文章主要為大家介紹了Java線程池隊列PriorityBlockingQueue和SynchronousQueue詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • spring4.3 實現(xiàn)跨域CORS的方法

    spring4.3 實現(xiàn)跨域CORS的方法

    下面小編就為大家分享一篇spring4.3 實現(xiàn)跨域CORS的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • MyBatis-Plus 復(fù)雜查詢Lambda+Wrapper 多條件功能實現(xiàn)

    MyBatis-Plus 復(fù)雜查詢Lambda+Wrapper 多條件功能實現(xiàn)

    通過本文的介紹,我們深入了解了MyBatis-Plus中Lambda+Wrapper的強大功能,它不僅極大地簡化了SQL的編寫,還提高了代碼的安全性和可維護性,感興趣的朋友跟隨小編一起看看吧
    2026-01-01

最新評論

弥勒县| 滨州市| 萨迦县| 阿拉善左旗| 高要市| 谢通门县| 汤原县| 勃利县| 临城县| 玉田县| 申扎县| 独山县| 克什克腾旗| 中牟县| 静海县| 三门峡市| 武夷山市| 扎赉特旗| 泸水县| 湘乡市| 腾冲县| 彰武县| 天柱县| 江达县| 合川市| 象山县| 双城市| 嘉荫县| 上蔡县| 武威市| 淳安县| 兴和县| 台前县| 绥德县| 涞源县| 黑水县| 湖口县| 八宿县| 海兴县| 镇原县| 额济纳旗|