在运行时动态更新规则。流口水+弹簧靴

时间:2018-11-13 08:50:23

标签: java spring spring-boot drools

所以目前我正在练习在Spring-boot(1.5.12.RELEASE)中使用Drools(7.13.0.Final)。我在Spring-boot中使用以下类制作了一个示例应用程序

型号:TaxiFare.java

@Data
public class TaxiFare {
    private double surge;
    private double netFare;
    private double baseFare;
    private double distanceTraveled;
}

服务:TaxiFareService.java

@Service
public class TaxiFareService {

    @Autowired
    private KieContainer kieContainer;


    public TaxiFare getTaxiFare(TaxiFare fare) {

        KieSession kieSession = kieContainer.newKieSession("rulesSession");

        kieSession.insert(fare);
        kieSession.fireAllRules();
        kieSession.dispose();
        return fare;
    }
}

RestController:TaxiFareController.java

@RestController
public class TaxiFareController {

    @Autowired
    private TaxiFareService taxiFareService;

    @RequestMapping(value = "/getFare", method = RequestMethod.GET)
    public String getQuestions(@RequestParam(required = true) double baseFare, @RequestParam(required = true) double surge, @RequestParam(required = true) double distanceTraveled) {

        TaxiFare fare = new TaxiFare();
        fare.setBaseFare(baseFare);
        fare.setSurge(surge);
        fare.setDistanceTraveled(distanceTraveled);

        taxiFareService.getTaxiFare(fare);

        return String.format("NET FARE IS: %s", fare.getNetFare());
    }


}

配置:

@Bean
public KieContainer kieContainer2() {
    return KieServices.Factory.get().getKieClasspathContainer();
}

具有已定义的规则

package rules

import com.samsung.bixby.management.drools.model.TaxiFare

rule "No Surge"
    when
        $fareObject: TaxiFare(surge == 0.0);
    then
        $fareObject.setNetFare($fareObject.getBaseFare() * $fareObject.getDistanceTraveled());
end
rule "Has Surge"
    when
        $fareObject: TaxiFare(surge > 0.0);
    then
        $fareObject.setNetFare($fareObject.getSurge() * $fareObject.getBaseFare() * $fareObject.getDistanceTraveled());
end

我已经使用网上找到的各种Drools + Spring集成教程来构建此示例应用程序。目前,规则引擎可以正常工作,但是我想做的是我希望能够在每次添加新规则或修改现有规则时在应用程序运行时动态重新加载规则文件。该应用程序打包为WAR,并部署在Web服务器中。

我已经阅读了多篇有关KieScanner的使用的文章,但是关于它的书面教程都没有意义,甚至文档本身也没有意义。按照他们提供的示例代码,

KieScanner kieScanner = kieServices.newKieScanner(kieContainer);

总是会导致构建失败,因为newKieScanner似乎无法基于提供的kieContainer创建kieScanner。有没有其他方法可以为Drools设置动态规则,或者澄清如何正确实施KieScanner?

谢谢。

3 个答案:

答案 0 :(得分:0)

您可以尝试一下,效果很好

 @Test
public void messageRuleFromUTFString() {
 String ruleContent =
     "package rules\r\n"+
     "import mypackage.Message\r\n" +
         "rule \"myrule\"\r\n" +
        "    \twhen\r\n" +
        "        $id : Message([\"38196-2\"] contains id)\r\n" +
        "    then\r\n" +
        "\t\tSystem.out.println(\"Works!\");\r\n" +
        "end\r\n";
    KieSession kSession = null;
    try {
        KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kb.add(ResourceFactory.newByteArrayResource(ruleContent.getBytes("utf-8")), ResourceType.DRL);

        KnowledgeBuilderErrors errors = kb.getErrors();
        for (KnowledgeBuilderError error : errors) {
            System.out.println(error);
        }
        InternalKnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
        kBase.addPackages(kb.getKnowledgePackages());
        kSession = kBase.newKieSession();
        kSession.insert(createMessage("38196-2"));
        kSession.fireAllRules();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } finally {
        if (kSession != null)
            kSession.dispose();
    }
}

提供给github用户之一的信用。我的示例略微修改为最新版本的口水: https://github.com/ityouknow/drools-examples.git

答案 1 :(得分:0)

您可以参考Edgex规则引擎,他们使用Drools规则引擎在运行时动态添加和删除规则。 请参考以下链接,同样可能会有所帮助。 https://github.com/edgexfoundry/support-rulesengine

答案 2 :(得分:0)

试试这个,效果很好

public kieSession kiaSession(String key, String rdlFile){

        KieFileSystem kieFileSystem = getKieFileSystem(rdlFile);
        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();
        KieModule kieModule = kieBuilder.getKieModule();
        KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());
        KieSession kieSession = kieContainer.newKieSession();
        return kieSession ;
    } 
   
private KieFileSystem getKieFileSystem(String rdlFile) {
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        kieFileSystem.write(ResourceFactory.newClassPathResource(rdlFile));
        return kieFileSystem;
    }

所以你可以这样称呼它

 KieSession session = this.droolsService.kiaSession("order.drl");
        session.insert(yourModel);
        session.fireAllRules();
        return order.toString();