如何在没有任何插件的情况下在 grails3 中使用 drools?
How to use drools in grails3 without any plugin?
是否可以在不安装任何插件的情况下在GRAILS3中使用drools规则引擎?我问这个是因为我知道流口水是在 java 中实现的,而 Ken Siprell 在 actual official plugin 中实现了 GRAILS(显然)不再起作用。
经过大量调查和尝试,我得到了一个小的 GRAILS3 API 服务,通过它可以在没有任何插件的情况下使用 DROOLS 引擎处理数据。这一切皆有可能,因为 DROOLS 基于 java 并且 GRAILS 与 Java 之间完美兼容。
您只需要以下内容:
- 在 build.gradle
中包含最小的 DROOLS 依赖
- 选择一个文件夹来存储files.drl
- 有一些实体可以用作要处理的事实(不强制保留它们,所以我跳过休眠配置)
- 实施服务以构建规则库知识并获取会话
- 在 API 控制器中实现一些方法以通过 DROOLS 处理数据(从服务中获取会话)
下面是一个简单的例子:
DROOLS 依赖项(在 build.gradle 中):
runtime "org.drools:drools-compiler:6.5.0.Final"
compile "org.drools:drools-core:6.5.0.Final"
compile "org.drools:knowledge-api:6.5.0.Final"
src/rules 中的 DRL 存储(将在服务中引用此路径,见下文):myrules.drl
import my.entities.Book;
import java.util.List;
rule "Find author"
salience 10
when
$book: Book( author=="Shakespeare" )
then
System.out.println("Book found, date:"+$book.getDate0());
end
一些实体,例如书:
package my.entities
import java.util.Date
class Book {
String title, author
Date date0
}
建立DROOLS知识和获取session的服务(我准备了一个无状态引擎,比有状态引擎更轻):
package my.services
import grails.converters.*
import org.kie.api.runtime.*;
import org.kie.internal.io.ResourceFactory;
import org.kie.api.*;
import org.kie.api.io.*;
import org.kie.api.builder.*;
class DroolsService {
def getSession() {
def path = "src/rules"
def lru = ["myrules.drl"]
def rules = []
lru.each{
rules.add("${path}${it}")
}
StatelessKieSession ksess = buildSession(rules)
return ksess
}
}
private buildSession(def lfile) {
println "Building DROOLS session..."
try {
def lres = []
lfile.each{
Resource resource = ResourceFactory.newFileResource(new File(it));
lres.add(resource)
}
KieContainer kieContainer = buildKieContainer(lres)
StatelessKieSession kieSession = kieContainer.newStatelessKieSession()
return kieSession
} catch(Exception e) {
e.printStackTrace()
return null
}
protected KieContainer buildKieContainer(def lres) {
KieServices kieServices = KieServices.Factory.get()
KieFileSystem kieFileSystem = kieServices.newKieFileSystem()
lres.each{
kieFileSystem.write("src/main/resources/rule.drl", it)
}
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll()
Results results = kieBuilder.results
if (results.hasMessages(Message.Level.ERROR)) {
throw new IllegalStateException(this.class.name + ": " + results.messages.toString())
}
KieContainer kieContainer = kieServices.newKieContainer(kieServices.repository.defaultReleaseId)
kieContainer
}
}
并在 API 控制器中使用服务:
class ApiController {
def droolsService
def proc = {
def sess = droolsService.getSession()
def mess = "ok DROOLS proc from JSON"
Book book = null
if (params.contbook) {
book = new Book(JSON.parse(params.contbook))
sess.execute book
}
response.status = 200
render mess
}
在控制器中,我从参数中获取 json 数据并用它们填充一个实体,以便使用由 DROOLS 服务初始化的规则引擎来执行它。当然,这是一个非常简单的解决方案,但它确实有效。
一些注意事项:
- 每个 drl 规则的 RHS 部分(在 "then" 之后)必须是 java,因此,如示例中,您不能直接访问实体的私有 属性,但您必须使用 getter 或 setter(由 GRAILS 隐式创建)
- getSession 创建一个新的知识构建和一个新会话,这不是最优的,您可以重新设计它以存储 DROOLS 会话,然后通过用户会话重用它
- 你可以在同一个文件夹中有多个 files.drl 然后你必须在服务中列出它们以便将它们打包到知识引擎中
希望所有有用的东西。
是否可以在不安装任何插件的情况下在GRAILS3中使用drools规则引擎?我问这个是因为我知道流口水是在 java 中实现的,而 Ken Siprell 在 actual official plugin 中实现了 GRAILS(显然)不再起作用。
经过大量调查和尝试,我得到了一个小的 GRAILS3 API 服务,通过它可以在没有任何插件的情况下使用 DROOLS 引擎处理数据。这一切皆有可能,因为 DROOLS 基于 java 并且 GRAILS 与 Java 之间完美兼容。
您只需要以下内容:
- 在 build.gradle 中包含最小的 DROOLS 依赖
- 选择一个文件夹来存储files.drl
- 有一些实体可以用作要处理的事实(不强制保留它们,所以我跳过休眠配置)
- 实施服务以构建规则库知识并获取会话
- 在 API 控制器中实现一些方法以通过 DROOLS 处理数据(从服务中获取会话)
下面是一个简单的例子:
DROOLS 依赖项(在 build.gradle 中):
runtime "org.drools:drools-compiler:6.5.0.Final"
compile "org.drools:drools-core:6.5.0.Final"
compile "org.drools:knowledge-api:6.5.0.Final"
src/rules 中的 DRL 存储(将在服务中引用此路径,见下文):myrules.drl
import my.entities.Book;
import java.util.List;
rule "Find author"
salience 10
when
$book: Book( author=="Shakespeare" )
then
System.out.println("Book found, date:"+$book.getDate0());
end
一些实体,例如书:
package my.entities
import java.util.Date
class Book {
String title, author
Date date0
}
建立DROOLS知识和获取session的服务(我准备了一个无状态引擎,比有状态引擎更轻):
package my.services
import grails.converters.*
import org.kie.api.runtime.*;
import org.kie.internal.io.ResourceFactory;
import org.kie.api.*;
import org.kie.api.io.*;
import org.kie.api.builder.*;
class DroolsService {
def getSession() {
def path = "src/rules"
def lru = ["myrules.drl"]
def rules = []
lru.each{
rules.add("${path}${it}")
}
StatelessKieSession ksess = buildSession(rules)
return ksess
}
}
private buildSession(def lfile) {
println "Building DROOLS session..."
try {
def lres = []
lfile.each{
Resource resource = ResourceFactory.newFileResource(new File(it));
lres.add(resource)
}
KieContainer kieContainer = buildKieContainer(lres)
StatelessKieSession kieSession = kieContainer.newStatelessKieSession()
return kieSession
} catch(Exception e) {
e.printStackTrace()
return null
}
protected KieContainer buildKieContainer(def lres) {
KieServices kieServices = KieServices.Factory.get()
KieFileSystem kieFileSystem = kieServices.newKieFileSystem()
lres.each{
kieFileSystem.write("src/main/resources/rule.drl", it)
}
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll()
Results results = kieBuilder.results
if (results.hasMessages(Message.Level.ERROR)) {
throw new IllegalStateException(this.class.name + ": " + results.messages.toString())
}
KieContainer kieContainer = kieServices.newKieContainer(kieServices.repository.defaultReleaseId)
kieContainer
}
}
并在 API 控制器中使用服务:
class ApiController {
def droolsService
def proc = {
def sess = droolsService.getSession()
def mess = "ok DROOLS proc from JSON"
Book book = null
if (params.contbook) {
book = new Book(JSON.parse(params.contbook))
sess.execute book
}
response.status = 200
render mess
}
在控制器中,我从参数中获取 json 数据并用它们填充一个实体,以便使用由 DROOLS 服务初始化的规则引擎来执行它。当然,这是一个非常简单的解决方案,但它确实有效。
一些注意事项:
- 每个 drl 规则的 RHS 部分(在 "then" 之后)必须是 java,因此,如示例中,您不能直接访问实体的私有 属性,但您必须使用 getter 或 setter(由 GRAILS 隐式创建)
- getSession 创建一个新的知识构建和一个新会话,这不是最优的,您可以重新设计它以存储 DROOLS 会话,然后通过用户会话重用它
- 你可以在同一个文件夹中有多个 files.drl 然后你必须在服务中列出它们以便将它们打包到知识引擎中
希望所有有用的东西。