一、环境概述

JDK:openjdk version "1.8.0_452"
Maven: maven 3.8.8
Drools:Drools 7.73.0.Final
SpringBoot:SpringBoot 2.7.18

二、项目依赖
这里没有引入drools-spring依赖了,是直接手动把组件IOC的。
POM.xml

<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring-boot.version>2.7.18</spring-boot.version><drools.version>7.73.0.Final</drools.version><lombok.version>1.18.30</lombok.version><junit.version>4.13.2</junit.version></properties><!-- 使用 dependencyManagement 管理 Spring Boot 和 Drools 版本 --><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-bom</artifactId><version>${drools.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!-- Drools依赖 --><dependency><groupId>org.drools</groupId><artifactId>drools-core</artifactId></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId></dependency><!-- 决策表要用 --><dependency><groupId>org.drools</groupId><artifactId>drools-decisiontables</artifactId></dependency><!-- SpringBoot依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><!-- 排除 JUnit 5(因为要用 JUnit 4) --><exclusions><exclusion><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId></exclusion><exclusion><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId></exclusion></exclusions></dependency><!-- 若为Web项目,添加此依赖 (二选一)--><!--        <dependency>--><!--            <groupId>org.springframework.boot</groupId>--><!--            <artifactId>spring-boot-starter-web</artifactId>--><!--        </dependency>--><!-- 若为非Web项目,添加此依赖 (二选一) 这里我就不用web跑了,直接starter跑了--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>provided</scope></dependency><!-- junit 4 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency></dependencies>

三、实体类和配置类
注意:这里没有用读取kmodule.xml的方式创建KieBase了,是直接代码配置类方式配置的
src/main/java/com/online/admin/entity/Person.java

package com.online.admin.entity;import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person
{private String name;private int age;
}

src/main/java/com/online/admin/config/DroolsConfig.java

package com.online.admin.config;import lombok.extern.slf4j.Slf4j;
import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.conf.EqualityBehaviorOption;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.IOException;/*** Drools配置类*/
@Slf4j
@Configuration
public class DroolsConfig {@Beanpublic KieServices getKieServices() {return KieServices.Factory.get();}/*** 这里就类似于读取kmodule.xml,创建模型类*/@Beanpublic KieModuleModel kieModuleModel(KieServices kieServices) {KieModuleModel kieModuleModel = kieServices.newKieModuleModel();KieBaseModel kieBaseModel1 = kieModuleModel.newKieBaseModel("rule1").setDefault(false).addPackage("rule1").setEqualsBehavior(EqualityBehaviorOption.EQUALITY).setEventProcessingMode(EventProcessingOption.STREAM);//有状态类型的Session就是规则执行过程中会话会一直存在,改变工作内存对象会再次触发规则判断,重新计算,重新输出结果。//无状态类型的Session就要求你在开始计算的时候把所需所有事实对象全部传入,执行完计算以后会话就不存在了,只是会返回结果。// 这里是用的有状态演示// 有状态类型kieBaseModel1.newKieSessionModel("ksession-rules1").setType(KieSessionModel.KieSessionType.STATEFUL);KieBaseModel kieBaseModel2 = kieModuleModel.newKieBaseModel("rule2").setDefault(false).addPackage("rule2").setEqualsBehavior(EqualityBehaviorOption.EQUALITY).setEventProcessingMode(EventProcessingOption.STREAM);// 有状态类型kieBaseModel2.newKieSessionModel("ksession-rules2").setType(KieSessionModel.KieSessionType.STATEFUL);return kieModuleModel;}// 这里我打算根据数据库或者配置中心读取配置创建,先读取Module配置,// 然后根据配置读取映射的drl文件位置,根据模块区分开不同模块下的的Session。// 这里是写死的,组件生命周期管理有问题,玩玩可以,项目上千万别学@Beanpublic KieFileSystem kieFileSystem(KieServices kieServices,KieModuleModel kieModuleModel) throws IOException {KieFileSystem kieFileSystem = kieServices.newKieFileSystem();ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();kieFileSystem.writeKModuleXML(kieModuleModel.toXML());// 1. 加载属于KieBase "rules1"的规则(路径:rule1/*.drl)Resource[] rule1Resources = resolver.getResources("classpath*:rule1/*.drl");for (Resource resource : rule1Resources) {// 规则文件路径对应KieBase1的package:"rule1"String resourcePath = "rule1/" + resource.getFilename();kieFileSystem.write(ResourceFactory.newClassPathResource(resourcePath, "UTF-8"));log.info("已加载KieBase(rules1)的规则文件: {}", resourcePath);}// 2. 加载属于KieBase "rules2"的规则(路径:rule2/*.drl)Resource[] rule2Resources = resolver.getResources("classpath*:rule2/*.drl");for (Resource resource : rule2Resources) {// 规则文件路径对应KieBase2的package:"rule2"String resourcePath = "rule2/" + resource.getFilename();kieFileSystem.write(ResourceFactory.newClassPathResource(resourcePath, "UTF-8"));log.info("已加载KieBase(rules2)的规则文件: {}", resourcePath);}return kieFileSystem;}@Beanpublic KieContainer kieContainer(KieServices kieServices, KieFileSystem kieFileSystem, KieModuleModel kieModuleModel) {// 构建KieModuleKieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);// 构建KieRepositoryKieRepository kieRepository = kieServices.getRepository();//这里我是自己玩搭建环境,用的默认的版本号,实际这里可能要自定义releaseId(规则版本号,用于区分规则版本是否发生变化用于热部署)kieRepository.addKieModule(kieRepository::getDefaultReleaseId);// 执行构建kieBuilder.buildAll();// 检查构建错误if (kieBuilder.getResults().hasMessages(Message.Level.ERROR)) {log.error("规则构建失败: {}", kieBuilder.getResults().getMessages());throw new RuntimeException("规则构建失败,请检查规则文件");}// 创建KieContainerreturn kieServices.newKieContainer(kieRepository.getDefaultReleaseId());}
}

四、drl文件(两个内容差不多,但是包名称和位置不一样)
src/main/resources/rule1/rule1.drl

package rule1;
import com.online.admin.entity.Person;rule "Age Check Rule"when$p : Person(age >= 18)thenSystem.out.println("[rules1规则触发] " + $p.getName() + " 是成年人,年龄: " + $p.getAge());
endrule "Check using eval"when$p : Person()eval( $p.getAge() >= 18 )thenSystem.out.println("rules1条件满足");
end

src/main/resources/rule2/rule2.drl

package rule2;
import com.online.admin.entity.Person;rule "Age Check Rule"when$p : Person(age < 18)thenSystem.out.println("[rules2规则触发] " + $p.getName() + " 不是成年人,年龄: " + $p.getAge());
endrule "Check using eval"when$p : Person()eval( $p.getAge() >= 18 )thenSystem.out.println("rules2条件满足");
end

五、测试类

package com.online.admin;import com.online.admin.config.DroolsConfig;
import com.online.admin.entity.Person;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.Collection;@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DroolsConfig.class)
public class AppTest {@Autowiredprivate KieContainer kieContainer;@Testpublic void testRule1() {KieSession kieSession = null;try {Collection<String> kieBaseNames = kieContainer.getKieBaseNames();log.info("kieBaseNames : {}", kieBaseNames);kieSession = kieContainer.newKieSession("ksession-rules1");KieBase kieBase = kieSession.getKieBase();log.info("kieBase : {}", kieBase.getKiePackages());
//            Rule rule=kieBase.getRule("rule1","Age Check Rule");
//            log.info("rule : {}", rule.getName());Person adult = new Person("李四", 25);kieSession.insert(adult);int firedRules = kieSession.fireAllRules();log.info("触发了 {} 条规则", firedRules);} catch (RuntimeException e) {log.error("规则执行失败", e);Assert.fail(e.getMessage());throw e;} finally {if (kieSession != null) {try {kieSession.dispose();} catch (RuntimeException e) {log.error("kiesession关闭失败,{}", e.getMessage());}}}}@Testpublic void testRule2() {KieSession kieSession = null;try {kieSession = kieContainer.newKieSession("ksession-rules2");Person adult = new Person("李四", 12);kieSession.insert(adult);int firedRules = kieSession.fireAllRules();log.info("触发了 {} 条规则", firedRules);} catch (RuntimeException e) {log.error("规则执行失败", e);Assert.fail(e.getMessage());throw e;} finally {if (kieSession != null) {try {kieSession.dispose();} catch (RuntimeException e) {log.error("kiesession关闭失败,{}", e.getMessage());}}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/921894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!