首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在没有插件的情况下使用grails3中的drools?

如何在没有插件的情况下使用grails3中的drools?
EN

Stack Overflow用户
提问于 2016-11-07 13:43:46
回答 1查看 281关注 0票数 1

在没有任何插件安装的情况下,可以在GRAILS3中使用drools规则引擎吗?我问这个问题,因为我知道drools是在java和实际官方插件中由Ken为GRAILS实现的(显然)不再起作用了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-11 15:49:28

经过大量的调查和多次尝试,我得到了一个小型的GRAILS3 API服务,通过它可以使用DROOLS处理数据,而无需任何插件。这一切都是可能的,因为DROOLS基于Java,而且GRAILS和java之间具有完美的兼容性。

你所需要的只是以下几点:

  1. 在build.gradle中包含最小的DROOLS依赖项
  2. 选择要存储files.drl的文件夹
  3. 有一些实体可以用作事实来处理(不强制持久化它们,所以我跳过hibernate配置)
  4. 实现服务以构建规则基础知识和获取会话
  5. 在API控制器中实现一些方法,通过DROOLS (从服务中获取其会话)处理数据。

下面是一个简单的例子:

DROOLS依赖项(在build.gradle中):

代码语言:javascript
复制
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

代码语言:javascript
复制
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

某些实体,例如,图书:

代码语言:javascript
复制
package my.entities
import java.util.Date

class Book {
    String title, author
    Date date0
}

构建DROOLS知识和获取会话的服务(我准备了一个无状态引擎,比有状态引擎更轻):

代码语言:javascript
复制
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控制器中使用服务:

代码语言:javascript
复制
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部分(在“so”之后)必须是java,因此,就像在示例中一样,您不能直接访问实体的私有属性,但是您必须使用getter或setter (由GRAILS隐式创建)。
  • getSession创建知识和新会话的新构建,这不是最优的,您可以重新设计它,以便存储DROOLS会话,然后通过用户会话重用它。
  • 您可以将多个files.drl放在同一个文件夹中,然后必须将它们全部列出在服务中,以便将它们打包到知识引擎中。

希望所有这些都是有用的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40466708

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档