规则引擎Drools在SpringBoot中使用

步骤

  • 创建规则引擎对象;
  • 向引擎中加载规则集或更换规则集;
  • 向引擎提交需要被规则集处理的数据对象集合;
  • 命令引擎执行;
  • 导出引擎执行结果,从引擎中撤出处理过的数据。

目录结构

image

1、添加drools相关pom依赖

        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-spring</artifactId>
            <version>${drools.version}</version>
            <exclusions>
                <!-- 依赖的spring版本全部以spring boot依赖的为准 -->
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-tx</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

2、创建Kie相关 Bean

package com.example.droolstest.droolstest.config;


import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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的服务类,方便在Rest接口中调用。 该类负责加载具体的drl规则文件,不再需要kmodule.xml配置文件了。
 */
@Configuration
public class DroolsAutoConfiguration {

    private static final String RULES_PATH = "rules/";


    /**
     * 创建Kie相关 Bean 使其被spring管理
     * @return
     * @throws IOException
     */
    @Bean
    @ConditionalOnMissingBean(KieFileSystem.class)
    public KieFileSystem kieFileSystem() throws IOException {
        KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();

        for (Resource file : getRuleFiles()){
            kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH+file.getFilename(),"utf-8"));
        }

        return kieFileSystem;
    }

    @Bean
    @ConditionalOnMissingBean(KieContainer.class)
    public KieContainer kieContainer() throws IOException {
        KieRepository kieRepository = getKieServices().getRepository();

        kieRepository.addKieModule(new KieModule() {
            @Override
            public ReleaseId getReleaseId() {
                return kieRepository.getDefaultReleaseId();
            }
        });

        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
        kieBuilder.buildAll();

        return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
    }


    private KieServices getKieServices(){
        return KieServices.Factory.get();
    }

    private Resource[] getRuleFiles() throws IOException {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        return resourcePatternResolver.getResources("classpath*:"+RULES_PATH+"**/*.*");
    }

    @Bean
    @ConditionalOnMissingBean(KieBase.class)
    public KieBase kieBase() throws IOException {
        return kieContainer().getKieBase();
    }

    // 不能反复被使用,释放资源后需要重新获取。
    // @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean
    @ConditionalOnMissingBean(KieSession.class)
    public KieSession kieSession() throws IOException {
        return kieContainer().newKieSession();
    }

    @Bean
    @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)
    public KModuleBeanFactoryPostProcessor kiePostProcessor() {
        return new KModuleBeanFactoryPostProcessor();
    }


}

3、创建drl规则文件


import com.example.droolstest.droolstest.actions.PersonRuleAction;
import com.example.droolstest.droolstest.dto.Person;

rule "规则1:根据名字找人"
    when
        $p : Person( name == "bob" )
    then
        PersonRuleAction.doAction($p, drools.getRule());
        System.out.println("规则名称是 [" + drools.getRule().getName() + "]");
end

rule "规则2:根据年龄范围找人"
    when
        $p : Person( age >= 25 && age < 65 )
    then
    System.out.println("规则名称是 [" + drools.getRule().getName() + "]");
        System.out.println( $p + "是适龄人!" );
end

4、创建实体对象

package com.example.droolstest.droolstest.dto;

public class Person {

    String name;
    int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

5、测试

package com.example.droolstest.droolstest;

import com.example.droolstest.droolstest.controller.RuleController;
import com.example.droolstest.droolstest.dto.Person;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
class DroolsTest {

    @Autowired
    RuleController ruleController;

    @Test
    public void test1Rule(){

        Person person = new Person();
        person.setName("bob");

        ruleController.personRule(person);

    }

    @Test
    public void test2Rule(){

        Person person1 = new Person();
        person1.setAge(26);
        person1.setName("bob");

        Person person2 = new Person();
        person2.setAge(25);
        person2.setName("二号");

        ruleController.personRule(person1);
        ruleController.personRule(person2);

    }

}

6、测试2结果

image

posted @ 2022-02-23 16:17  西红柿里没有番茄  阅读(551)  评论(1编辑  收藏  举报