当前位置: 首页 > wzjs >正文

全国建筑资质查询系统搜索引擎优化的主要内容

全国建筑资质查询系统,搜索引擎优化的主要内容,网页升级紧急通知写作,校园网的网站建设内容文章目录 前言一、创建规则库二、SpringBootDrools程序1.Maven依赖2.application.yml3.Mapper.xml4.Drools配置类5.Service6.Contoller7.测试接口 前言 公司的技术方案想搭建Drools自定义规则库配合大模型进行数据的校验。本篇用来记录使用SpringBoot配合Drools开发Demo程序。…

文章目录

  • 前言
  • 一、创建规则库
  • 二、SpringBoot+Drools程序
    • 1.Maven依赖
    • 2.application.yml
    • 3.Mapper.xml
    • 4.Drools配置类
    • 5.Service
    • 6.Contoller
    • 7.测试接口


前言

公司的技术方案想搭建Drools+自定义规则库配合大模型进行数据的校验。本篇用来记录使用SpringBoot配合Drools开发Demo程序。

初步设计的技术方案为:使用数据库存储DRL文件,在程序启动时将所有的DRL文件加载到程序。接口传入数据时要带有想要做规则判断的DRL文件key值,支持多个key。面对规则库的数据有修改或增添时,理想方案是监听数据库的修改,然后将增量或修改加载到程序。也可以通过定时任务的方式定时全量重新加载,但就没办法实现实时生效。也可以暴露接口手动重新加载。

以上为初步的技术方案,很多地方还比较粗糙,如果有比较成熟的方案欢迎大家交流。


一、创建规则库

我这里用的MySql数据库
建表语句如下

DROP TABLE IF EXISTS `drools_rules`;
CREATE TABLE `drools_rules`  (`id` int(11) NOT NULL AUTO_INCREMENT,`rule_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,`rule_content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,`version` int(11) NULL DEFAULT 1,`enabled` tinyint(1) NULL DEFAULT 1,`last_modified` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0),PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Compact;

主要就是将DRL文件以文本的格式存到数据库里
DRL例子如下:

rule "手术麻醉方式必填校验" @BusinessType("diagnosis_check")when$data: org.example.drools.domain.vo.ClinicalData(anesthesiaMethod == null || anesthesiaMethod.isEmpty())$result: org.example.drools.domain.vo.ValidationResult()then$result.addError("RULE_001", "手术记录必须包含麻醉方式");end

二、SpringBoot+Drools程序

1.Maven依赖

我这里Java用的11版本

		<!-- Drools --><dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>7.69.0.Final</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>7.69.0.Final</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-mvel</artifactId><version>7.69.0.Final</version> <!-- 确保版本与 drools-core 一致 --></dependency>

2.application.yml

server:port: 9528
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://XXXX:3306/drools_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: root
logging:level:org.springframework: INFOcom.example.drools: DEBUG
mybatis-plus:type-aliases-package: com.example.drools.domainmapper-locations: classpath*:mapper/**/*Mapper.xml

3.Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.drools.mapper.DroolsDemoMapper"><select id="findAllEnabledRules" resultType="org.example.drools.domain.entity.DroolsRules">SELECT *FROM drools_rules rWHERE r.enabled = 1ORDER BY r.version DESC</select>
</mapper>

获取数据库中所有生效的规则,按版本倒排

4.Drools配置类

package org.example.drools.config;import org.example.drools.domain.entity.DroolsRules;
import org.example.drools.mapper.DroolsDemoMapper;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.runtime.KieContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;/*** Drools 动态配置*/
@Configuration
public class DroolsConfig {//操作规则库的Mapper@Autowiredprivate DroolsDemoMapper droolsDemoMapper;@Beanpublic KieContainer kieContainer() {KieServices kieServices = KieServices.get();KieFileSystem kieFileSystem = kieServices.newKieFileSystem();reloadRules(kieFileSystem); // 初始化加载规则KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);kieBuilder.buildAll();KieModule kieModule = kieBuilder.getKieModule();return kieServices.newKieContainer(kieModule.getReleaseId());}// 动态重新加载规则public void reloadRules(KieFileSystem kieFileSystem) {List<DroolsRules> rules = droolsDemoMapper.findAllEnabledRules();rules.forEach(rule ->kieFileSystem.write(String.format("src/main/resources/%s.drl", rule.getRuleName()),rule.getRuleContent()));}
}

初始化加载所有规则到Drools的容器中

5.Service

package org.example.drools.service;import org.drools.core.base.RuleNameEqualsAgendaFilter;
import org.example.drools.config.DroolsConfig;
import org.example.drools.domain.vo.ClinicalData;
import org.example.drools.domain.vo.ValidationResult;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.definition.KiePackage;
import org.kie.api.definition.rule.Rule;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.AgendaFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;@Service
public class DroolsService {@Autowiredprivate KieContainer kieContainer;@Autowiredprivate DroolsConfig droolsConfig;private static Map<String, String> ruleMetadataMap = new HashMap<>();/*** 初始化元数据*/@PostConstructprivate void init() {KieBase kieBase = kieContainer.getKieBase();for (KiePackage pkg : kieBase.getKiePackages()) {for (Rule rule : pkg.getRules()) {org.drools.core.definitions.rule.impl.RuleImpl ruleImpl =(org.drools.core.definitions.rule.impl.RuleImpl) rule;// 提取元数据String businessType = (String) ruleImpl.getMetaData().get("BusinessType");ruleMetadataMap.put(rule.getName(), businessType);}}}public ValidationResult validate(ClinicalData request) {KieSession kieSession = kieContainer.newKieSession();ValidationResult result = new ValidationResult();//kieSession.setGlobal("errors", result.getErrors());kieSession.insert(request);kieSession.insert(result);AgendaFilter filter = activation -> {String ruleName = activation.getRule().getName();String businessType = ruleMetadataMap.get(ruleName);return request.getRuleTypes().contains(businessType);};kieSession.fireAllRules(filter);kieSession.dispose();return result;}}

当我们将所有的规则初始化加载到Drools的容器中后,如果直接使用接口参数执行规则判断,那么Drools将使用参数走过所有的规则判断,而实际的场景中我这些参数只想执行部分规则,那么就引出过滤规则的问题。

当时在处理这个问题的时候也是问了大模型的方案,当时大模型给出了一个比较麻烦的方案,就是在DRL文件中使用类似自定义注解的东西将DRL的一个业务编码写进去,具体写法可以看上面我展示的DRL文件例子,@BussinessType那个。然后后面就一直研究这个方案如何实现。

后面整理的时候发现其实有很简单的方法就能实现这个问题,我先说这个麻烦的方案是如何实现的,后面补充上简单的方案

麻烦的方案是:在将所有的规则加载到容器中后,遍历所有规则,将规则的name作为key,将DRL文件中的@BussinessType的字段取出作为value存在一个Map中,然后编写Drools的过滤器

 AgendaFilter filter = activation -> {String ruleName = activation.getRule().getName();String businessType = ruleMetadataMap.get(ruleName);return request.getRuleTypes().contains(businessType);};

简单的方案是:接口传参的时候直接传rule_name的集合,反正都是定死的,传name和bussinessType没区别,然后过滤器直接request.getRuleTypes().contains(ruleName)就行了。

6.Contoller

@RestController
@RequestMapping("/drools")
@Api(tags = "Drools测试 API", description = "提供Drools测试相关的 Rest API")
public class DroolsController {@Autowiredprivate DroolsService droolsService;@PostMapping("/test")public ValidationResult validateClinicalData(@RequestBody ClinicalData request) {return droolsService.validate(request);}
}
@Data
@ApiModel(value = "ClinicalData")
public class ClinicalData {@ApiModelProperty("麻醉方式")private String anesthesiaMethod;// 门(急)诊诊断编码(ICD-10)@ApiModelProperty("门(急)诊诊断编码")private String emergencyDiagnosisCode;@ApiModelProperty("规则类型集合")private Set<String> ruleTypes;public String getAnesthesiaMethod() {return anesthesiaMethod;}public void setAnesthesiaMethod(String anesthesiaMethod) {this.anesthesiaMethod = anesthesiaMethod;}public String getEmergencyDiagnosisCode() {return emergencyDiagnosisCode;}public void setEmergencyDiagnosisCode(String emergencyDiagnosisCode) {this.emergencyDiagnosisCode = emergencyDiagnosisCode;}public Set<String> getRuleTypes() {return ruleTypes;}public void setRuleTypes(Set<String> ruleTypes) {this.ruleTypes = ruleTypes;}
}

7.测试接口

在这里插入图片描述
附上结果返回的实体类结构以及我测试使用的两个DRL文件

@Data
public class ValidationResult {// 校验错误信息列表private List<String> errors = new ArrayList<>();// 校验通过标记public boolean isValid() {return errors.isEmpty();}// 添加带错误码的信息public void addError(String errorCode, String message) {errors.add(String.format("[%s] %s", errorCode, message));}public List<String> getErrors() {return errors;}public void setErrors(List<String> errors) {this.errors = errors;}
}
rule "手术麻醉方式必填校验" @BusinessType("diagnosis_check")when$data: org.example.drools.domain.vo.ClinicalData(anesthesiaMethod == null || anesthesiaMethod.isEmpty())$result: org.example.drools.domain.vo.ValidationResult()then$result.addError("RULE_001", "手术记录必须包含麻醉方式");end
function Boolean isValidDiagnosisCode(String code) {if (code == null || code.isEmpty()) return false;Character firstChar = Character.toUpperCase(code.charAt(0));return (firstChar >= 'A' && firstChar <= 'U') || firstChar == 'Z';
}
rule "诊断编码范围校验" @BusinessType("code_check")when$data: org.example.drools.domain.vo.ClinicalData(emergencyDiagnosisCode != null,!isValidDiagnosisCode(emergencyDiagnosisCode))$result: org.example.drools.domain.vo.ValidationResult()then$result.addError("RULE_002", "诊断编码各项编码范围应为:A~U开头和Z开头的编码");end

文章转载自:

http://d2HZzYDZ.qftzk.cn
http://GR3l7kbg.qftzk.cn
http://3BaaPvZb.qftzk.cn
http://gTti5bI3.qftzk.cn
http://SRcpna8U.qftzk.cn
http://vLk6WMXb.qftzk.cn
http://Zn1ARyiF.qftzk.cn
http://XGzzWOFG.qftzk.cn
http://CF80ZMf6.qftzk.cn
http://JzQw9k4L.qftzk.cn
http://7nb8xhuK.qftzk.cn
http://no6kDpDb.qftzk.cn
http://0l91bYVl.qftzk.cn
http://KGnYgD6S.qftzk.cn
http://9CBAHsiP.qftzk.cn
http://N1d8kfnw.qftzk.cn
http://ByGUCiSc.qftzk.cn
http://5pxYnFwd.qftzk.cn
http://8g5p0tFo.qftzk.cn
http://3nf5h8V6.qftzk.cn
http://uGNBEIxL.qftzk.cn
http://9ogylta9.qftzk.cn
http://A9bTPNmv.qftzk.cn
http://j9yiVLzB.qftzk.cn
http://rKlpJtrw.qftzk.cn
http://rOnyd2Ty.qftzk.cn
http://5Er7HmQ0.qftzk.cn
http://VYYO6jxz.qftzk.cn
http://erVTU4UE.qftzk.cn
http://w9q7JCTW.qftzk.cn
http://www.dtcms.com/wzjs/655525.html

相关文章:

  • 做网站需要招聘内容范本wordpress get_post_mime_type
  • 苏州网站制作网络建设公司网站死循环
  • 小企业官方网站制作图片生成链接的app
  • 公司后台网站怎么做个人简历模板表格下载
  • 网站编辑如何做八年级信息所用软件做网站
  • 所有网站的分辨率关于做好全国网站建设
  • 怎么防止网站被注册机去哪个网站做试用好
  • 济南企业网站关键词推广服务器安全
  • 平台网站空间乌鲁木做兼职的网站
  • 做色网站网站空间排名
  • 建网站免费程序做设计最好的参考网站
  • 网站的优点缺点商业网站建设咨询
  • 网站建设是不是无形资产网站开发定制合同范本
  • 网站开发项目实战视频wordpress缓存与手机版动态切换
  • 做网站推销话术如何招聘软件网站开发人员
  • 常州网站建设选思创做电商网站用什么软件开发
  • 如何采集网站文章软件开发工具包括
  • 网站建设三层架构实训报告招代理的网站要怎么做
  • 做网站公司无锡门户网站建设基本情况
  • 深圳企业建网站软文推广发稿
  • 品牌建设 网站昆明住房和城乡建设局网站
  • 互联网App网站建设方案wordpress 例子
  • 在郑州网站建设wordpress文章前端按钮
  • 电商网站订货广东广州免费建站
  • 手机如何创建简易网站一流的网站建设
  • 大理中小企业网站建设温州建设工程信息网站
  • 怎么用腾讯云主机建设网站适合夜晚使用的十大app
  • 做橡胶应该看什么网站成功的微网站
  • 为什么要建设图书馆网站机械设备怎样做网络推广
  • 酒店行业网站建设方案福州小程序开发平台