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

drools规则引擎

1 单个文件

这个大多搜索导的都是把规则放到一个文件,这个是基础,但是实际应用就不太方便。如果你使用的jdk1.8,那么对应的drools版本为7.x

1.1 pom依赖

 <drools.version>7.74.1.Final</drools.version>  
<dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId><version>${drools.version}</version> <!-- 请根据需要选择合适的版本 --></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-decisiontables</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-mvel</artifactId><version>${drools.version}</version></dependency>

1.2 droolsconfig

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.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DroolsConfig {@Beanpublic KieContainer  initKieContainer() {KieServices kieServices = KieServices.Factory.get();KieFileSystem kieFileSystem = kieServices.newKieFileSystem();kieFileSystem.write(ResourceFactory.newClassPathResource("rules/gszy.drl"));KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);kieBuilder.buildAll();KieModule kieModule = kieBuilder.getKieModule();return kieServices.newKieContainer(kieModule.getReleaseId());}}

1.3 controller层

注意下面请求和响应返回值是分开的

    @Autowiredprivate KieContainer kisContainer;@PostMapping("gszy")public ResponseResult<GszyRespDto> gszy(@RequestBody GszyReqDto req){GszyRespDto gszyRespDto = new GszyRespDto();KieSession kieSession = kisContainer.newKieSession();kieSession.insert(req);kieSession.insert(gszyRespDto);kieSession.fireAllRules();kieSession.dispose();//ResponseResult<GszyRespDto> resp = new ResponseResult<>(true);resp.setData(gszyRespDto);return resp;}

1.4 drl文件

在idea中下载jboss插件,安装drools插件。

  这里讲请求和响应参数分开,drl中用的java语言,可以自定义function。从下面来看可以写的比较复杂的业务逻辑。

package   com.mms.rules;
import com.dzmsoft.acc.mms.rules.dto.req.GszyReqDto;
import com.dzmsoft.acc.mms.rules.dto.resp.GszyRespDto;rule "验证输入"when$req : GszyReqDto(dzsr == 0.0)thenthrow new IllegalArgumentException("请输入年收入总额");
endrule "检查总收入是否足以支付社保和公积金"when$req : GszyReqDto(dzsr < (dsb * 12.0 + dgjj * 12.0))thenthrow new IllegalArgumentException("总收入不足以负担社保和公积金");
endrule "规则1"when$req : GszyReqDto()$res : GszyRespDto()$dzsr : Double() from $req.getDzsr()$dsb : Double() from $req.getDsb()$dgjj : Double() from $req.getDgjj()$dckx : Double() from $req.getDckx()thendouble dAllCKX = 60000.0 + $dsb * 12.0 + $dgjj * 12.0 + $dckx * 12.0;$res.setDAllCKX(dAllCKX);modify($res) {};
endrule "规则2"when$req : GszyReqDto()$res : GszyRespDto()eval($req.getDzsr() <= $res.getDAllCKX())thendouble dygz = $req.getDzsr() / 12.0;int nygz = (int) dygz;if (nygz % 50 != 0) {nygz += (50 - (nygz % 50));dygz = nygz;}$res.setDygz(dygz);$res.setDnzj(0.0);$res.setDgs(0.0);$res.setDsfl(0.0);$res.setDshsr($req.getDzsr() - ($req.getDsb() + $req.getDgjj()) * 12.0);modify($res) {};
endrule "规则3"when$req : GszyReqDto()$res : GszyRespDto()eval($req.getDzsr() > $res.getDAllCKX())thendouble dygzTemp = $res.getDAllCKX() / 12.0;int nygz = (int) dygzTemp;if (nygz % 50 != 0) {nygz += (50 - (nygz % 50));dygzTemp = nygz;}double dMings = 100000000.0; // 初始设置为一个很大的值double dOptygz = 0.0;while (true) {if (dygzTemp * 12.0 > $req.getDzsr()) {break;}double dgzynssde = dygzTemp * 12.0 - $res.getDAllCKX();double dnzjynssde = $req.getDzsr() - dygzTemp * 12.0;double dgzgs = calGzgs(dgzynssde);double dnzjgs = calNzjgs(dnzjynssde);if (dgzgs + dnzjgs < dMings) {dMings = dgzgs + dnzjgs;dOptygz = dygzTemp;}dygzTemp += 50.0;}$res.setDygz(dOptygz);$res.setDnzj($req.getDzsr() - dOptygz * 12.0);$res.setDgs(dMings);$res.setDsfl(dMings / $req.getDzsr() * 100.0);$res.setDshsr($req.getDzsr() - ($req.getDsb() + $req.getDgjj()) * 12.0 - dMings);modify($res) {};end

2 多个规则文件

2.1 写定路径方式

        可以看到下面的DRL文件,多了一个就写一个,这种方式也可以可以的。

   @Beanpublic KieContainer  initKieContainer() {KieServices kieServices = KieServices.Factory.get();KieFileSystem kieFileSystem = kieServices.newKieFileSystem();// 添加多个 DRL 文件kieFileSystem.write(ResourceFactory.newClassPathResource("rules/gszy.drl"));kieFileSystem.write(ResourceFactory.newClassPathResource("rules/nzjzy.drl"));// 构建 KieModuleKieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);kieBuilder.buildAll();// 检查构建是否有错误if (kieBuilder.getResults().hasMessages(org.kie.api.builder.Message.Level.ERROR)) {throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().getMessages().toString());}KieModule kieModule = kieBuilder.getKieModule();return kieServices.newKieContainer(kieModule.getReleaseId());}

   但为什么启动会重复,看来规则文件虽然可以拆分,但是规则名称不能重复。

2.2 模糊路径方式

drools本身是不支持的,需要通过java代码来实现,按照相对路径的写法。

 @Beanpublic KieContainer  initKieContainer() {KieServices kieServices = KieServices.Factory.get();KieFileSystem kieFileSystem = kieServices.newKieFileSystem();// 添加多个 DRL 文件// 指定 DRL 文件所在的目录String drlDirectory = "rules";// 获取类路径资源ClassPathResource resource = new ClassPathResource(drlDirectory);// 扫描目录并加载所有 DRL 文件try {File file = resource.getFile();Path directoryPath = file.toPath();// 扫描目录并加载所有 DRL 文件try (Stream<Path> paths = Files.walk(directoryPath)) {List<File> drlFiles = paths.filter(Files::isRegularFile).filter(path -> path.toString().endsWith(".drl")).map(Path::toFile).collect(Collectors.toList());for (File drlFile : drlFiles) {kieFileSystem.write(ResourceFactory.newFileResource(drlFile));}}} catch (IOException e) {throw new RuntimeException("Error loading DRL files from directory: " + drlDirectory, e);}// 构建 KieModuleKieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);kieBuilder.buildAll();// 检查构建是否有错误if (kieBuilder.getResults().hasMessages(org.kie.api.builder.Message.Level.ERROR)) {throw new RuntimeException("Build Errors:\n" + kieBuilder.getResults().getMessages().toString());}KieModule kieModule = kieBuilder.getKieModule();return kieServices.newKieContainer(kieModule.getReleaseId());}


http://www.mrgr.cn/news/35051.html

相关文章:

  • Linux入门学习:深刻理解计算机硬件与OS体系
  • golang strings api接口
  • Python项目的质量保证
  • 内容生态短缺,Rokid AR眼镜面临市场淘汰赛
  • 责任链模式优化 文章发布的接口(长度验证,敏感词验证,图片验证等环节) 代码,示例
  • 数据结构---线性表之顺序表
  • 9.24-k8s服务发布
  • 基于C语言开发(控制台)通讯录管理程序
  • Java之路--搞定数据类型及运算符已如探囊取物
  • golang学习笔记11-模块化与包管理【重要】
  • 32岁前端干了8年,是继续做前端开发,还是转其它工作_ui设计师转开发
  • pwd 命令:显示当前工作目录
  • 嵌入式工程师需要拥有哪些能力?
  • 第二讲 数据结构
  • 百度C++一面-面经总结
  • 制药污水处理设备流程说明介绍
  • 2024年最强网络安全学习路线,详细到直接上清华的教材!
  • 【Linux 报错】“userdel: user xxxx is currently used by process xxx”
  • 基类和派生类的赋值对象转换、派生类与基类成员的函数隐藏、派生类中的默认成员函数、继承与友元、继承与静态成员函数、菱形继承、菱形虚拟继承等的介绍
  • Java:Object操作