美文网首页设计方案
Drools集成SpringBootStarter

Drools集成SpringBootStarter

作者: 木木与呆呆 | 来源:发表于2021-01-20 15:53 被阅读0次

    1.说明

    基于fast-drools-spring-boot-starter,
    能够方便的将规则引擎Drools集成到Spring Boot,
    基于前面介绍过的文章
    Drools集成SpringBoot,
    进一步改造成使用fast-drools-spring-boot-starter的项目。

    2.fast-drools-spring-boot-starter

    项目地址:
    Fast Drools

    项目特性:

    • SpringBoot与Drools快速整合,不需要配置繁琐的kmodule.xml,也不需要自己编写代码初始化Drools
    • 指定文件名执行评估规则,更加直观的流程分析
    • 规则文件动态加载
    • 规则文件分组控制
    • 使用NIO的文件映射,更快速的文件的读写
    • 基于缓存的规则文件控制,更高效的规则评估
    • 支持各种路径格式
    • 支持xls和xlsx格式的规则表文件
    • 日志监控流程中规则与评估对象的动态
    • 执行速度与性能的极致,且可定制

    注意:
    这是第三方个人开发的开源项目,
    不推荐在正式项目中使用,
    但是作者已经把jar包等发布到了阿里云的仓库,
    所以国内的同学使用起来还是比较方便的。

    3.创建Maven工程

    pom.xml工程信息:

    <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.ai.prd</groupId>
        <artifactId>drools-fast-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <description>Based on fast-drools-spring-boot-starter, Drools integrats into the Spring Boot</description>
    </project>
    

    4.引入Spring Boot相关依赖

    引入spring-boot-starter-web作为Web工程,对外提供Rest服务,
    引入spring-boot-starter-log4j2日志框架,打印测试匹配结果,
    引入spring-boot-starter-test测试框架,开发Junt5测试用例:

    <properties>
        <spring-boot.version>2.3.1.RELEASE</spring-boot.version>
    </properties>
    
    <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>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <exclusions>
                <!-- 单元测试不使用Junit4,使用Junit5 -->
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    

    5.引入Drools相关依赖

    引入fast-drools-spring-boot-starter即可:

    <properties>
        <fast.drools.version>8.0.7</fast.drools.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>com.github.hongwen1993</groupId>
            <artifactId>fast-drools-spring-boot-starter</artifactId>
            <version>${fast.drools.version}</version>
        </dependency>
    </dependencies>
    

    6.开发启动类

    启动类DroolsApplication.java:

    package com.ai.prd.drools;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class DroolsApplication {
        public static void main(String[] args) {
            SpringApplication.run(DroolsApplication.class, args);
        }
    }
    

    7.操作对象Person

    下面会对Person对象进行规则过滤,
    这里给出定义Person.java:

    package com.ai.prd.drools.entity;
    
    public class Person {
        private String name;
    
        private int age;
    }
    

    8.开发规则文件

    在src/main/resources/rules/com/ai/prd/目录下新建文件
    ai-rules.drl:

    package com.ai.prd
     
    import com.ai.prd.drools.entity.Person;
    import com.ai.prd.drools.action.PersonRuleAction;
    
    // 根据名字匹配指定的人
    rule "1.find target person"
        when
            $p : Person( name == "bob" )
        then
            PersonRuleAction.doParse($p, drools.getRule());
            System.out.println("Rule name is [" + drools.getRule().getName() + "]"); 
            System.out.println("Rule package is [" + drools.getRule().getPackageName() + "]");
    end
    
    // 根据年龄匹配找到打工人
    rule "2.find the work person"
        when
            $p : Person( age >= 25 && age < 65 )      
        then
            System.out.println( $p + " is a work person!" );
    end
    

    规则1匹配名字为bob的人,并且调用工具类PersonRuleAction打印相关日志,
    同时打印规则的名称和包路径到控制台。
    规则2匹配年龄在25到65之间的打工人,
    然后把匹配到的人直接打印到控制台。

    9.规则处理类

    PersonRuleAction.java在匹配到相应规则时被调用,
    此处仅实现日志打印的功能:

    package com.ai.prd.drools.action;
    
    import org.drools.core.definitions.rule.impl.RuleImpl;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.ai.prd.drools.entity.Person;
    
    /**
     * 触发Person相关的规则后的处理类
     */
    public class PersonRuleAction {
        private static Logger LOG = LoggerFactory.getLogger(PersonRuleAction.class);
    
        // 目前只实现记录日志功能
        public static void doParse(Person person, RuleImpl rule) {
            LOG.debug("{} is matched Rule[{}]!", person, rule.getName());
        }
    }
    

    10.配置application.yml

    在src/main/resources下新建application.yml:

    server:
      port: 5117
      
    # 指定规则文件文件夹,会自动扫描该目录下所有规则文件,决策表,以及CSV文件
    spring:
      drools:
        path: classpath:rules/**/*.drl
        # 可以指定全局的mode,选择stream或cloud
        mode: stream
        # 指定规则文件自动更新的周期,单位秒,默认30秒扫描一次
        update: 10
        listener: on 
    

    指定了应用运行的端口,
    以及Drools相关的配置。

    11.新建日志配置文件

    在src/main/resources目录下,
    新建日志配置文件Log4j2.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout
                    pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            </Console>
            <RollingFile name="RuleResultFile"
                fileName="log/rule_result.log"
                filePattern="log/backup/rule_result-%i.log">
                <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%l] - %msg%n" />
                <Policies>
                    <SizeBasedTriggeringPolicy size="10MB" />
                </Policies>
                <DefaultRolloverStrategy max="10" />
            </RollingFile>
        </Appenders>
        <Loggers>
            <Logger name="com.ai.prd.drools.action" level="DEBUG"
                additivity="true">
                <AppenderRef ref="RuleResultFile" />
            </Logger>
            <Root level="INFO">
                <AppenderRef ref="Console" />
            </Root>
        </Loggers>
    </Configuration>
    

    日志文件配置后,
    PersonRuleAction类打印的日志
    不仅会输出到log/rule_result.log,
    也会输出到控制台。

    12.开发Junit5测试用例

    针对上面规则文件中配置的规则,
    开发两个Junit5的测试用例,
    在src/test/java/目录下
    创建DroolsApplicationTest.java:

    package com.ai.prd.drools;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    import org.junit.jupiter.api.AfterAll;
    import org.junit.jupiter.api.BeforeAll;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.TestInstance;
    import org.kie.api.runtime.KieSession;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import com.ai.prd.drools.entity.Address;
    import com.ai.prd.drools.entity.Person;
    import com.drools.core.KieTemplate;
    
    @SpringBootTest
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    public class DroolsApplicationTest {
    
        @Autowired
        private KieTemplate kieTemplate;
    
        private KieSession kSession;
    
        @BeforeAll
        public void initKieSession() {
            // 每次测试都要重新获取kSession
            // 同时可以指定要加载的规则文件
            kSession = kieTemplate.getKieSession("ai-rules.drl");
        }
    
        @AfterAll
        public void runDispose() {
            // 全部测试用例执行完毕后,需要手动释放资源
            kSession.dispose();
        }
    
        @Test
        public void test1findTargetPerson() {
            Person bob = new Person();
            bob.setName("bob");
            kSession.insert(bob);
    
            Person other = new Person();
            other.setName("other1");
            kSession.insert(other);
    
            int rules = kSession.fireAllRules();
            // 按照规则1只有bob能够匹配上
            assertEquals(1, rules);
        }
    
        @Test
        public void test2findWorkPerson() {
            Person bob = new Person();
            bob.setAge(33);
            kSession.insert(bob);
    
            Person other = new Person();
            other.setAge(88);
            kSession.insert(other);
    
            int rules = kSession.fireAllRules();
            assertEquals(1, rules);
        }
    

    注意这里的KieTemplate是fast-drools-spring-boot-starter提供的,
    而不是以前kie-spring提供的KieContainer了。

    13.运行测试用例

    DroolsApplicationTest执行后,
    控制台输出:

    15:46:02.441 [main] INFO  com.ai.prd.drools.DroolsApplicationTest - Starting DroolsApplicationTest on yuwen-asiainfo with PID 3836 (started by yuwen in D:\Code\Work\drools\drools-demos\drools-fast-demo)
    15:46:02.443 [main] INFO  com.ai.prd.drools.DroolsApplicationTest - No active profile set, falling back to default profiles: default
    15:46:03.387 [main] INFO  org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor'
    15:46:03.701 [main] INFO  com.ai.prd.drools.DroolsApplicationTest - Started DroolsApplicationTest in 1.524 seconds (JVM running for 2.704)
    15:46:04.081 [main] WARN  org.drools.compiler.kie.builder.impl.KieBuilderImpl - File 'file0.drl' is in folder '' but declares package 'com.ai.prd'. It is advised to have a correspondance between package and folder names.
    15:46:04.911 [main] WARN  org.drools.compiler.kie.builder.impl.KieBuilderImpl - File 'file0.drl' is in folder '' but declares package 'com.ai.prd'. It is advised to have a correspondance between package and folder names.
    15:46:05.723 [main] DEBUG com.ai.prd.drools.action.PersonRuleAction - Person [name=bob, birthDay=null, age=0, address=null] is matched Rule[1.find target person]!
    Rule name is [1.find target person]
    Rule package is [com.ai.prd]
    Person [name=null, birthDay=null, age=33, address=null] is a work person!
    15:46:05.748 [SpringContextShutdownHook] INFO  org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor - Shutting down ExecutorService 'applicationTaskExecutor'
    

    相关文章

      网友评论

        本文标题:Drools集成SpringBootStarter

        本文链接:https://www.haomeiwen.com/subject/ahmkzktx.html