天天看點

Drools規則引擎入門Drools規則引擎入門

Drools規則引擎入門

Drools(JBoss Rules )具有一個易于通路企業政策、易于調整以及易于管理的開源業務規則引擎,符合業内标準,速度快、效率高。業務分析師或稽核人員可以利用它輕松檢視業務規則,進而檢驗是否已編碼的規則執行了所需的業務規則。

Drools 5.x版本代碼(淘汰)

pom.xml

檔案,内容:引入單元測試、drools、slf4j包

<properties>
        <drools-version>7.0.0.Final</drools-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>${drools-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>
    </dependencies>
           

com.mylitboy.drools.model.Product.java

檔案,内容:類型及折扣

/** 産品類 */
public class Product {

    // 鑽石
    public static final String DIAMOND = "0";
    // 黃金
    public static final String GOLD = "1";

    // 類别
    private String type;
    // 折扣
    private int discount;

    // Getter/Setter
}
           

resources/com/rules/Rules.drl

檔案,内容為相關規則内容。

package com.rules

import com.mylitboy.drools.model.Product

rule Offer4Diamond
    when
        productObject : Product(type==Product.DIAMOND)
    then
        productObject.setDiscount(15);
     end

rule Offer4Gold
    when
        productObject : Product(type==Product.GOLD)
    then
        productObject.setDiscount(30);
     end
           

Test.java

檔案,用于單元測試規則引擎。

@Test
public void oldExecuteDrools() {
    
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    // 添加規則檔案。
    kbuilder.add(ResourceFactory.newClassPathResource("com/rules/Rules.drl", this.getClass()), ResourceType.DRL);
    // 校驗規則是否有問題。
    if (kbuilder.hasErrors()) {
        System.out.println(kbuilder.getErrors().toArray());
    }

    // 擷取規則中的包
    Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();
    // 添加規則中的包到規則base
    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
    // 将KnowledgePackage 集合添加到KnowledgeBase中
    kbase.addKnowledgePackages(pkgs);

    // 擷取KnowledgeSession
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

    Product product = new Product();
    product.setType(Product.GOLD);
    
    // 引入比對請求
    ksession.insert(product);
    // 比對所有規則
    ksession.fireAllRules();
    // 銷毀
    ksession.dispose();

    System.out.println("The discount for the product " + product.getType() + " is " + product.getDiscount() + "%");
}
           

運作單元測試,結果如下:

The discount for the product 1 is 30%
           

Drools 7.x版本代碼

com.mylitboy.drools.model.Product.java

檔案,内容:類型及折扣,參考

Drools 5.x版本代碼

resources/com/rules/Rules.drl

檔案,内容為相關規則内容,參考

Drools 5.x版本代碼

pom.xml

檔案,引入kie-spring、kie-api、drools-compiler包:

<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-spring</artifactId>
    <version>7.9.0.Final</version>
    <exclusions>
        <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>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.9.0.Final</version>
</dependency>
<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-api</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>
           

新增檔案:

resources/META-INF/kmodule.xml

檔案

<?xml version="1.0" encoding="utf-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="rules" packages="com.rules">
        <ksession name="ksession-rule"/>
    </kbase>
</kmodule>
           

單元測試代碼:

@Test
public void testRules() {
    // 建構KisServices
    KieServices ks = KieServices.Factory.get();
    // 根據Classpath:MATE-INF目錄加載kmodule.xml檔案
    KieContainer kieContainer = ks.getKieClasspathContainer();
    // 擷取kmodule.xml中配置的名稱為ksession-rule的session,預設為有狀态的。
    KieSession kSession = kieContainer.newKieSession("ksession-rule");

    Product product = new Product();
    product.setType(Product.GOLD);

    // 添加product FACT對象
    kSession.insert(product);
    // 進行規則判斷
    int count = kSession.fireAllRules();
    System.out.println("命中了" + count + "條規則!");
    System.out.println("商品" + product.getType() + "的商品折扣為" + product.getDiscount() + "%");
}
           

運作單元測試,結果如下:

命中了1條規則!
商品1的商品折扣為30%
           

Drools內建至SpringBoot

建立SpringBoot項目

com.mylitboy.drools.model.Product.java

檔案,内容同上。

resources/com/rules/Rules.drl

檔案,内容同上。

DroolsAutoConfiguration.java

檔案,内容:

@Configuration
public class DroolsAutoConfiguration {
    private static final String RULES_PATH = "com/rules/";

    @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;
    }

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

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

        kieRepository.addKieModule(new KieModule() {
            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();
    }

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

    @Bean
    @ConditionalOnMissingBean(KieSession.class)
    public KieSession kieSession() throws IOException {
        return kieContainer().newKieSession();
    }

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

}
           

單元測試:

@RunWith(SpringRunner.class)
@SpringBootTest
public class DroolsSpringbootApplicationTests {
    @Resource
    private KieSession kieSession;

    @Test
    public void test(){
        Product product = new Product();
        product.setType(Product.GOLD);

        // 添加product FACT對象
        kieSession.insert(product);
        // 進行規則判斷
        int count = kieSession.fireAllRules();
        System.out.println("命中了" + count + "條規則!");
        System.out.println("商品" + product.getType() + "的商品折扣為" + product.getDiscount() + "%");
    }
}
           

單元測試結果:

命中了1條規則!
商品1的商品折扣為30%