Drools rule engine (including dynamically loaded rule engine in the database)

Drools rule engine

Article directory

  • Drools rules engine
  • foreword
  • 1. What is a rule engine?
  • 2. Introduction to Drools
    • 1. Before and after the introduction of the rule engine program architecture:
    • 2. Drools API development steps:
    • insert image description here
  • 3. Drools Quick Start
    • 1. Use the project file as the rule engine
    • 2. Use database storage rule engine
  • 4. Composition of Drools rule engine and its core classes
  • Summarize

Foreword

With the continuous development of the Internet, there are many platforms that have relatively complex business rules and these rules will change frequently according to requirements. At this time, it is necessary to find a technology that can decouple activity rules and codes, that is, a rule engine.

1. What is a rule engine?

Rule engine: the full name is business rule management system, and the English name is BRMS. The main idea of the rule engine is to separate the business decision part of the application, and use the predefined semantic module to write the business decision (business rule), which is configured and managed by the user or developer when needed. It should be noted that the rule engine is not a specific technical framework, but refers to a type of system, namely the business rule management system.

Java open source rule engines include: Drools, Easy Rules, Mandarax, IBM ILOG. The most widely used and open source is Drools.

Main application scenarios:

  • Risk control system——-risk loan, risk assessment
  • Anti-fraud project —– bank loan, credit verification
  • Decision-making platform——-financial calculation
  • E-commerce platform —— full reduction, discount, price increase purchase

2. Introduction to Drools

Drools is an open source rule engine written in the Java language that uses the Rete algorithm to evaluate the rules written. Drools allows business logic to be expressed declaratively. Rules can be written in a non-XML local language to decouple the rules from the business code. The rules are stored in a file in the form of scripts, so that the changes to the rules do not need to modify the code, and restart the machine to take effect in the online environment. Also, you can embed Java code directly into the rules file, which makes learning Drools even more attractive.

Official website: http://www.drools.org/#
Official documentation: http://www.drools.org/learn/documentation.html

1. Before and after the introduction of the rule engine program structure:

Before introduction:

After importing:

2. Drools API development steps:

3. Drools Quick Start

1. Use the project file as a rule engine

The examples in the HUAWEI CLOUD Developer Alliance articles cited in this chapter are linked as follows. The second chapter using the database as a rule engine is original

Original link: https://huaweicloud.csdn.net/63356f78d3efff3090b56d8f.html

E-commerce platform promotion point rules

Under 100 yuan, no extra points
100-500 yuan plus 100 points
500 yuan-1000 yuan plus 500 points
More than 1000 yuan plus 1000 points

Development and implementation
Step 1: Create a Maven project and add Drools rule engine dependencies.

 <!--Add rule engine dependency-->
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>7.73.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-mvel</artifactId>
            <version>7.73.0.Final</version>
        </dependency>
        <!--Add unit test tool class-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

Step 2: Create resources/META-INF/kmodule.xml configuration file according to drools requirements

There needs to be a configuration file to tell where the code rule file drl is. In drools, this file is kmodule.xml.

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <!--
    name: Specify the kbase name, which can be arbitrary but must be unique
    packages: specifies the directory where the rule file is stored, and fills in according to the actual situation
    default: Specifies whether the current kbase is the default
    -->
    <kbase name="rules" packages="rules" default="true">
        <!--
        name: Specify the ksession name, which can be arbitrary but must be unique
        default: Specifies whether ksession is the default
        -->
        <ksession name="ksession-rules" default="true"/>
    </kbase>
</kmodule>

Step 3: Create a business entity object

package com.zzg.model;

public class Order implements java.io.Serializable {<!-- -->

    private int amount; //order amount

    private int score; //order points

    @Override
    public String toString() {<!-- -->
        return "Order{" +
                "amount=" + amount +
                ", score=" + score +
                '}';
    }

    public int getAmount() {<!-- -->
        return amount;
    }

    public void setAmount(int amount) {<!-- -->
        this.amount = amount;
    }

    public int getScore() {<!-- -->
        return score;
    }

    public void setScore(int score) {<!-- -->
        this.score = score;
    }
}

Step 4: Create a rule file in resources/rules/score-rules.drl

package rules;

import com.zzg.model.Order;

// No extra points for less than 100 yuan
rule "score_1"
when
    $order:Order(amount<100);
then
    $order.setScore(0);
    System.out.println("Trigger below 100 yuan, no points");
end
// 100-500 yuan, plus 100 points
rule "score_2"
when
    $order:Order(amount>100 & amp; & amp; amount <= 500);
then
    $order.setScore(100);
    System.out.println("Trigger 100-500 yuan, add 100 points");
end
// 500-10000 yuan, plus 500 points
rule "score_3"
when
    $order:Order(amount>500 & amp; & amp; amount <= 1000);
then
    $order.setScore(500);
    System.out.println("Trigger 500-1000 yuan, add 500 points");
end
// more than 1000 yuan, plus 1000 points
rule "score_4"
when
    $order:Order(amount>1000);
then
    $order.setScore(1000);
    System.out.println("Trigger is greater than 1000 yuan, add 1000 points");
end

Step 5: Unit Testing

package com.zzg;

import com.zzg.model.Order;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class TestDrools {<!-- -->
    @Test
    public void test1() {<!-- -->
        // first step
        KieServices kieServices = KieServices.Factory.get();
        // second step
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        // third step
        KieSession kieSession = kieContainer. newKieSession();
        // business object
        Order order = new Order();
        order. setAmount(100);
        // the fourth step
        kieSession.insert(order);
        // Step 5: Execute the rule engine
        kieSession.fireAllRules();
        // Step 6: close the session
        kieSession.dispose();

        System.out.println("The result after specifying the rule engine: " + order.getScore());

    }
}

Effect screenshot:

23:01:01.112 [main] INFO org.drools.compiler.kie.builder.impl.KieContainerImpl - End creation of KieBase: rules
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was HALTING is now INACTIVE
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now DISPOSED
Result after specifying rule engine: 0

2. Use database storage rule engine

E-commerce platform promotion point rules

Under 100 yuan, no extra points
100-500 yuan plus 100 points
500 yuan-1000 yuan plus 500 points
More than 1000 yuan plus 1000 points

Development and implementation
Step 1: Create a Maven project and add Drools rule engine dependencies.

 <!--Add rule engine dependency-->
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>7.73.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-api</artifactId>
            <version>7.73.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>7.73.0.Final</version>
        </dependency>
        <!--Add unit test tool class-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

Step 2: Create the resources/META-INF/kmodule.xml configuration file according to the requirements of drools Because the rules are read in the database, it is found through testing that the kmodule.xml configuration file is not written

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <!--
    name: Specify the kbase name, which can be arbitrary but must be unique
    packages: specifies the directory where the rule file is stored, and fills in according to the actual situation
    default: Specifies whether the current kbase is the default
    -->
    <kbase name="rules" packages="rules" default="true">
        <!--
        name: Specify the ksession name, which can be arbitrary but must be unique
        default: Specifies whether ksession is the default
        -->
        <ksession name="ksession-rules" default="true"/>
    </kbase>
</kmodule>

Step 3: Create a business entity object

package com.zzg.model;

public class Order implements java.io.Serializable {<!-- -->

    private int amount; //order amount

    private int score; //order points

    @Override
    public String toString() {<!-- -->
        return "Order{" +
                "amount=" + amount +
                ", score=" + score +
                '}';
    }

    public int getAmount() {<!-- -->
        return amount;
    }

    public void setAmount(int amount) {<!-- -->
        this.amount = amount;
    }

    public int getScore() {<!-- -->
        return score;
    }

    public void setScore(int score) {<!-- -->
        this.score = score;
    }
}

Step 4: Create a rule file and use the insert into statement to insert into the database (oracle database)

The database fields are serialNo (primary key), rule (rule content) rule type is CLOB
Here I use another way of writing, if you use the above way of writing, you can also, the above way of writing is still standard! ! !

DECLARE
V_LANG CLOB :=
'package rules
import com.zzg.model.Order;
\t
// No extra points for less than 100 yuan
rule "score_1"
when
context:Order(amount<100)
then
context.setScore(0);
System.out.println("Trigger below 100 yuan, no points");
end
// 100-500 yuan, plus 100 points
rule "score_2"
when
context:Order(amount>100 & amp; & amp; & amp; amount <= 500);
then
context.setScore(100);
System.out.println("Trigger 100-500 yuan, add 100 points");
end
// 500-10000 yuan, plus 500 points
rule "score_3"
when
context:Order(amount>500 & amp; & amp; & amp; amount <= 1000);
then
context.setScore(500);
System.out.println("Trigger 500-1000 yuan, add 500 points");
end
// more than 1000 yuan, plus 1000 points
rule "score_4"
when
context:Order(amount>1000);
then
context.setScore(1000);
System.out.println("Trigger is greater than 1000 yuan, add 1000 points");
end';
BEGIN
insert into t_rule(serialNo, rule) values (1, V_LANG);
END;

I didn’t test it here, if you copy it directly, there may be something wrong, and the above package may have problems, because the code is not on the local computer. Feel sorry.
Step 5: Unit Testing

package com.zzg;

import com.zzg.model.Order;
import org.junit.Test;
import org.kie.io.ResourceType;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.Clob;
import java.sql.SQLException;

public class TestDrools {<!-- -->
    @Test
    public void test1() {<!-- -->
        // The first step is to read the rules in the database. Here, everyone writes according to the framework of the persistence layer of their own project.
        // The type of rule in the entity class is private Clob rule;
RuleEntity ruleEntity = ruleDao. getRuleEntity();
// The second step is to convert the clob type to String type
String myRule = clobToString(ruleEntity. getRule());
// The third step is to create a rule object and convert the String to a DRL rule
KieHelper kieHelper = new KieHelper();
kieHelper.addContent(myRule, ResourceType.DRL);
// The fourth step is the session object, used to interact with the rule engine
KieSession kieSession = kieHelper.build().newKieSession();
        // business object
        Order order = new Order();
        order. setAmount(100);
        // the fourth step
        kieSession.insert(order);
        // Step 5: Execute the rule engine
        kieSession.fireAllRules();
        // Step 6: close the session
        kieSession.dispose();

        System.out.println("The result after specifying the rule engine: " + order.getScore());

    }
\t
private String clobToString(Clob clob) throws Exception{<!-- -->
String str = "";
// get stream
Reader rd = clob. getCharacterStream();
BufferedReader br = new BufferedReader(rd );
String s = br. readLine();
StringBuilder sb = new StringBuilder();
        while(s != null) {<!-- -->
          sb.append(s);
          s = br. readLine();
        }
        str = sb.toString();
        return str;
}
}

attach
Write here the addition, deletion, modification and query syntax of this field
Original link: https://huaweicloud.csdn.net/63355c9ad3efff3090b5418d.html?spm=1001.2101.3001.6650.3 & amp;utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~activity-3-12026 2609 -blog-126691379.pc_relevant_recovery_v2 & depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~activity-3-120262609-blog-126691379.pc_relevant_recovery_v2 & amp;utm_relevant_index=6

--Use PL/SQL syntax and solve it by binding variables instead of directly splicing SQL
DECLARE
    V_LANG CLOB := 'Massive strings to be inserted';
    V_UPDATE CLOB := 'updated mass character string';
BEGIN
 INSERT INTO temp t VALUES ('Grand.Jon', 22, V_LANG); --Increase
 UPDATE temp t SET t.temp_clob = V_UPDATE WHERE rownum = 1; --Modify
 SELECT t.NAME, dbms_lob.substr(t.temp_clob) FROM TEMP t; --Query Convert CLOB to character type
 DELETE temp t WHERE rownum = 1; --Delete by column
 COMMIT;
END;
/

Effect screenshot:

23:01:01.112 [main] INFO org.drools.compiler.kie.builder.impl.KieContainerImpl - End creation of KieBase: rules
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was HALTING is now INACTIVE
23:01:01.144 [main] DEBUG org.drools.core.common.DefaultAgenda - State was INACTIVE is now DISPOSED
Result after specifying rule engine: 0

4. Drools rule engine composition and its core classes

Drools rule engine composition
The drools rule engine consists of the following parts:

  • Working Memory
  • Rules (rule base)
  • Inference Engine
  • Among them, the Inference Engine (t reasoning engine) includes the following:

Pattern Match (matcher) specifically matches which rule, and it is done by it

  • Agenda
  • Execution Engine

Drools rule engine concept
Working Memory: Working memory, the drools rule engine will get data from Working Memory and perform pattern matching with the rules defined in the rule file, so the application we develop only needs to insert our data into Working Memory can be used. For example, in this case, we call kieSession.insert(order) to insert the order object into the working memory.

Fact: Fact means that in the application of drools rules, the object after inserting a common JavaBean into the Working Memory is the Fact object. For example, the Order object in this case belongs to the Fact object. The Fact object is a bridge or channel for data interaction between our application and the rule engine.

Rules: rule base, the rules we define in the rule file will be loaded into the rule base.

Pattern Matcher: Matcher, pattern matching all rules in Rule Base with Fact objects in Working Memory, the matching rules will be activated and put into Agenda.

Agenda: Agenda, which is used to store the rules that are activated after pattern matching by the matcher.

Summary

The above is what I want to talk about today. This article only briefly introduces the Drools rule engine, and Drools provides a large number of functions and methods that allow us to process data quickly and conveniently. You can take a look at the original link, which explains some basic grammar about Drools.

Reference article:
Read Drools rule engine: https://huaweicloud.csdn.net/63356f78d3efff3090b56d8f.html
[Drools] Getting started with Drools (1) Drools tutorial (including dynamic loading rule files): http://t.csdn.cn/jyfF0
CLOB introduction and use in Oracle: https://huweiloud.csdn.net/63355c9ad3eff3090b5418d.html? SPM = 1001.2101.3001.6650.3 & amp; UTM_MEDIUM = distrib UTE.PC_RELELEVANT.NONE-Task-BLOG-2 ~ DEFAULT ~ Ctrlist ~ Activity -3-120262609-blog-126691379.pc_relevant_recovery_v2 &depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~activity-3-120262609-blog-126691379.pc_re levant_recovery_v2 &utm_relevant_index=6