A recent project required a rules engine to solve the problem. After some research, Drools was selected as the main technology stack. Below, I will share the experience and summary of the technologies involved.
1. What are Drools?
Drools is a Business Rules Management System (BRMS) solution. It provides a core Business Rules Engine (BRE), a web authoring and rules management application (Drools Workbench), full runtime support for Decision Model and Notation (DMN) models at Conformance level 3 and an Eclipse IDE plugin for core development.
Drools is a business Rules Management System (BRMS) solution. Drools provides a set of solutions relevant to the rules business.
2. Why Drools?
When we write code, we often write code that is riddled with logical judgment conditions. See Figure 2-1
Figure 2-1
As requirements are iterated and optimized, such ifs inevitably increase, whether the depth of the judgment increases, or if/else increases, or the size of the judgment field increases, and each update of the large code can become a headache. Faced with this problem, some people may say that the strategic model can solve the problem better. But today we’re going to use a different solution — the rules engine.
3. Use tutorials
3.1 the key pom. XML
<properties>
<drools-version>7.51.0. The Final</drools-version>
</properties>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools-version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools-version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>${drools-version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>${drools-version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${drools-version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>${drools-version}</version>
</dependency>
</dependencies>
Copy the code
3.2 Drools sample
Demo.drl:
import java.util.HashMap;
import java.util.Map;
rule "ruleName"
when
$map:Map(this['age'] > 20.1)
then
$map.put("result".1);
end
Copy the code
Does that sound like if/else? When the condition in when is satisfied, the logic in then is executed.
3.3 Operation Demonstration:
Normally, for the rules engine, we would make an xxx. DRLS file, find the DRLS storage path through the kmodule. XML configuration, and load the specified Drools file to run.
But there is a problem. If Drools were to change, wouldn’t they have to re-upload and re-publish the service?
So, let’s talk about another way to load Drools rules, dynamically.
Let’s start with a piece of code:
/** ** class */
public class Student {
/** * age */
private Integer age;
/** * Height */
private Integer weight;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight; }}Copy the code
@Test
public void droolsStudent() {
String drools = "xxx.xxx.xxx.xxx.Student\n" +
"\n" +
"rule \"rule1\"\n" +
" when\n" +
" stu:Student(age>18 || weight < 180)\n" +
" then\n" +
"System.out.println(\" The age of the student is: \" + stu.getage ()); \n" +
"System.out.println(\" student weight is: \" + stu.getweight ()); \n" +
"end";
try {
KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
kb.add(ResourceFactory.newByteArrayResource(drools.getBytes("utf-8")), ResourceType.DRL);
// If it is a drools file, use resourcetype.drl
if (kb.hasErrors()) {
String errorMessage = kb.getErrors().toString();
System.out.println("Regular syntax exception --\n" + errorMessage);
return;
}
InternalKnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
kBase.addPackages(kb.getKnowledgePackages());
Student student = new Student();
student.setAge(20);
student.setWeight(200);
// Loads the executable session instance corresponding to the specified knowledge base
StatelessKieSession kieSession = kBase.newStatelessKieSession();
// Load the input parameter
kieSession.execute(student);
} catch(Exception e) { e.printStackTrace(); }}Copy the code
Execution Result:
Here, we don’t need the.drls file, we don’t need the kmodule. XML file, we just need a string, the string of the Drools file. And strings we can store in a database and pull them out when we need them. Even if it needs to be changed, it can be changed directly through the configuration page.
4. Technology expansion.
Someone might ask. Drools can be run through Java, so can Java be run through Drools?
The answer is: yes. We can call one of our Java methods directly from a Drools file. Without further ado, let’s get right to the demo.
@Autowired
private DroolsService droolsService;
@Test
public void droolsStudent() {
String drools = "xxx.xxx.xxx.xxx.Student; \n" +
"global xxx.xxx.xxx.xxx.DroolsService droolsService; \n" + // Here we refer to our global Service
"\n" +
"rule \"rule1\"\n" +
" when\n" +
" stu:Student(age>18 || weight < 180)\n" +
" then\n" +
"System.out.println(\" The age of the student is: \" + stu.getage ()); \n" +
"System.out.println(\" student weight is: \" + stu.getweight ()); \n" +
" droolsService.javaFunction(stu); \n" +
"end\n";
try {
KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
kb.add(ResourceFactory.newByteArrayResource(drools.getBytes("utf-8")), ResourceType.DRL);
if (kb.hasErrors()) {
String errorMessage = kb.getErrors().toString();
System.out.println("Regular syntax exception --\n" + errorMessage);
return;
}
InternalKnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
kBase.addPackages(kb.getKnowledgePackages());
Student student = new Student();
student.setAge(20);
student.setWeight(200);
// Loads the executable session instance corresponding to the specified knowledge base
StatelessKieSession kieSession = kBase.newStatelessKieSession();
// Add a global Service
kieSession.setGlobal("droolsService", droolsService);
// Load the input parameter
kieSession.execute(student);
} catch(Exception e) { e.printStackTrace(); }}Copy the code
/ * * * * / global class
@Service
public class DroolsService {
/** * DRL calls service *@param student* /
public void javaFunction(Student student) {
System.out.println("Drools invokes the Java"+JSONObject.toJSONString(student)); }}Copy the code
The result is as follows:
That’s it. Let our Drools load a global class that runs the specified complex logic.
5, summary
This time, mainly because of recent projects that use technologies that are new to me. Drools makes it possible to separate the logic, especially the if part, but if the if and else parts are too complex, I recommend doing it in code.
Drools is not only used to solve these rule problems, such as rule sets, Decision trees, score cards, etc., which can or are recommended to be done with Drools, but also has an important application scenario, Decision Flow ————, which combines Drools with BPMN.
There are activiti and other solutions for this area, but we don’t need to use BPMN2.0 and Drools ecosphere to do it, and we will update it soon when we are free.
For the syntax of Drools, such as ruleflow-group, lock-on-active, etc., you can read it separately.Copy the code