栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

drools详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

drools详解

1、基本的概念
请参考这个链接,差不多的语法感觉都介绍了
drools-api的基本语法链接

2、如何将drl文件配置在数据库中,实现动态加载:

package com.neo.drools;

import com.neo.drools.model.Message;
import org.kie.api.io.ResourceType;
import org.kie.internal.KnowledgeBase;
import org.kie.internal.KnowledgeBaseFactory;
import org.kie.internal.builder.KnowledgeBuilder;
import org.kie.internal.builder.KnowledgeBuilderError;
import org.kie.internal.builder.KnowledgeBuilderErrors;
import org.kie.internal.builder.KnowledgeBuilderFactory;
import org.kie.internal.io.ResourceFactory;
import org.kie.internal.runtime.StatefulKnowledgeSession;

import java.io.UnsupportedEncodingException;


public class DdLoadTest {
	public static void main(String[] args) {
		//rule,rule2可以放在数据库中,有个唯一code和他们对于,代码要执行规则的时候,根据code从数据库获取出来就OK了,这样自己开发的规则管理系统那边对数据库里的规则进行维护就行了
		String rule = "package com.neo.droolsrn";
		rule += "import com.neo.drools.model.Message;rn";
		rule += "rule "rule1"rn";
		rule += "twhenrn";
		rule += "Message( status == 1, myMessage : msg )";
		rule += "tthenrn";
		rule += "ttSystem.out.println( 1+":"+myMessage );rn";
		rule += "endrn";


		String rule2 = "package com.neo.droolsrn";
		rule += "import com.neo.drools.model.Message;rn";

		rule += "rule "rule2"rn";
		rule += "twhenrn";
		rule += "Message( status == 2, myMessage : msg )";
		rule += "tthenrn";
		rule += "ttSystem.out.println( 2+":"+myMessage );rn";
		rule += "endrn";


		StatefulKnowledgeSession kSession = null;
		try {


			KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
			//装入规则,可以装入多个
			kb.add(ResourceFactory.newByteArrayResource(rule.getBytes("utf-8")), ResourceType.DRL);
			kb.add(ResourceFactory.newByteArrayResource(rule2.getBytes("utf-8")), ResourceType.DRL);

			KnowledgeBuilderErrors errors = kb.getErrors();
			for (KnowledgeBuilderError error : errors) {
				System.out.println(error);
			}
			KnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
			kBase.addKnowledgePackages(kb.getKnowledgePackages());

			kSession = kBase.newStatefulKnowledgeSession();


			Message message1 = new Message();
			message1.setStatus(1);
			message1.setMsg("hello world!");

			Message message2 = new Message();
			message2.setStatus(2);
			message2.setMsg("hi world!");

			kSession.insert(message1);
			kSession.insert(message2);
			kSession.fireAllRules();

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


3、如何读取drl、决策表、csv文件:

注意:下文中的RULES_PATH,其实就是配置在resource下的路径,会通过kieFileSystem组件去读取这个目录下的所有文件。

配置drl文件的配置类(springboot+drl配置方式)

package com.itheima.drools.config;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.Resource;
import java.io.IOException;

@Configuration
public class DroolsConfig {
    //指定规则文件存放的目录
    private static final String RULES_PATH = "rules/";
    private final KieServices kieServices = KieServices.Factory.get();
    @Bean
    @ConditionalOnMissingBean
    public KieFileSystem kieFileSystem() throws IOException {
        System.setProperty("drools.dateformat","yyyy-MM-dd");
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        ResourcePatternResolver resourcePatternResolver =
                new PathMatchingResourcePatternResolver();
        Resource[] files =
                resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "*.*");
        String path = null;
        for (Resource file : files) {
            path = RULES_PATH + file.getFilename();
            kieFileSystem.write(ResourceFactory.newClassPathResource(path, "UTF-8"));
        }
        return kieFileSystem;
    }
    @Bean
    @ConditionalOnMissingBean
    public KieContainer kieContainer() throws IOException {
        KieRepository kieRepository = kieServices.getRepository();
        kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());
        kieBuilder.buildAll();
        return kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
    }
    @Bean
    @ConditionalOnMissingBean
    public KieBase kieBase() throws IOException {
        return kieContainer().getKieBase();
    }
    @Bean
    @ConditionalOnMissingBean
    public KModuleBeanFactoryPostProcessor kiePostProcessor() {
        return new KModuleBeanFactoryPostProcessor();
    }
}




根据文件,不管是drl文件,还是excel表格,或者是csv文件,将其动态的转换成字符串,这段代码很牛掰

	
    public String encodeToString(String realPath) {
        File file = new File(realPath);
        if (!file.exists()) {
            return null;
        }
        // drl文件
        if (realPath.endsWith(SUFFIX_DRL)) {
            return read(file);
        }
        InputStream is = null;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            logger.error("file not fount.");
        }
        // excel文件 xls和xlsx都支持
        // @author fbf
        if (realPath.endsWith(SUFFIX_EXCEL)||realPath.endsWith(SUFFIX_EXCEL_2007)) {
            return new SpreadsheetCompiler().compile(is, InputType.XLS);
        }
        // csv文件
        if (realPath.endsWith(SUFFIX_CSV)) {
            return new SpreadsheetCompiler().compile(is, InputType.CSV);
        }
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                logger.error("close stream error=>", e);
            }
        }
        return "package src.main.resources;";
    }



	
    private String read(File file) {
        FileInputStream fis = null;
        ByteArrayOutputStream bos = null;
        try {
            fis = new FileInputStream(file);
            bos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, length);
            }
            return bos.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bos != null) {
                    bos.close();
                }
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return null;
    }



	//这里还有很重要的一步,不管是excel,还是drl,最终会变解析为字符串
	//这个字符串是需要被解析运行的,如下:
	
	
    public KieSession decodeToSession(String... drl) {
        KieHelper kieHelper = new KieHelper();
        for (String s : drl) {
            kieHelper.addContent(s, ResourceType.DRL);
        }
        Results results = kieHelper.verify();
        if (results.hasMessages(Message.Level.WARNING, Message.Level.ERROR)) {
            List messages = results.getMessages(Message.Level.WARNING, Message.Level.ERROR);
            for (Message message : messages) {
                logger.error("Error: {}", message.getText());
            }
            throw new IllegalStateException("Compilation errors.");
        }
        KieBaseConfiguration config = kieHelper.ks.newKieBaseConfiguration();

        if (EventProcessingOption.STREAM.getMode().equalsIgnoreCase(getMode())) {
            config.setOption(EventProcessingOption.STREAM);
        } else {
            config.setOption(EventProcessingOption.CLOUD);
        }
        KieBase kieBase = kieHelper.build(config);
        KieSession kieSession = kieBase.newKieSession();
        if (getListener() == null || !LISTENER_CLOSE.equalsIgnoreCase(getListener())) {
            kieSession.addEventListener(new DefaultRuleRuntimeEventListener());
            kieSession.addEventListener(new DefaultAgendaEventListener());
            kieSession.addEventListener(new DefaultProcessEventListener());
        }
        return kieSession;
    }
KieBase kieBase = kieHelper.build();
		kieBase.addEventListener(new DefaultKieBaseEventListener(){
			@Override
			public void beforeKiePackageRemoved(BeforeKiePackageRemovedEvent event) {
				super.beforeKiePackageRemoved(event);
				String packageName = event.getKiePackage().getName();
				System.out.println("beforeKiePackageRemoved : " + packageName);
			}
		});

		kieBase.removeKiePackage("com.rules");

4、设置拦截器等,大致的意思就是在实时对象插入或者修改或者删除的时候 做一些拦截,然后动态的加载逻辑,这是drools官方为我们提供的扩展东西,挺好的!!!

	 KieBase kieBase = kieHelper.build(config);
        KieSession kieSession = kieBase.newKieSession();
        if (getListener() == null || !LISTENER_CLOSE.equalsIgnoreCase(getListener())) {
            kieSession.addEventListener(new DefaultRuleRuntimeEventListener());
            kieSession.addEventListener(new DefaultAgendaEventListener());
            kieSession.addEventListener(new DefaultProcessEventListener());
        }
        return kieSession;
package com.drools.core.listener;

import org.kie.api.event.rule.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DefaultAgendaEventListener implements AgendaEventListener {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void matchCreated(MatchCreatedEvent event) {
        logger.info("===>>匹配的规则:{}", event.getMatch().getRule());
    }

    @Override
    public void matchCancelled(MatchCancelledEvent event) {

    }

    @Override
    public void beforeMatchFired(BeforeMatchFiredEvent event) {
        logger.info("===>>开始执行Java代码块,匹配规则:{},评估对象:{}",
                event.getMatch().getRule(), event.getMatch().getFactHandles());
    }

    @Override
    public void afterMatchFired(AfterMatchFiredEvent event) {
        logger.info("===>>结束执行Java代码块,匹配规则:{},评估对象:{}",
                event.getMatch().getRule(), event.getMatch().getFactHandles());
    }

    @Override
    public void agendaGroupPopped(AgendaGroupPoppedEvent event) {

    }

    @Override
    public void agendaGroupPushed(AgendaGroupPushedEvent event) {

    }

    @Override
    public void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {

    }

    @Override
    public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {

    }

    @Override
    public void beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {

    }

    @Override
    public void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {

    }
}


package com.drools.core.listener;

import org.kie.api.event.process.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DefaultProcessEventListener implements ProcessEventListener {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void beforeProcessStarted(ProcessStartedEvent event) {

    }

    @Override
    public void afterProcessStarted(ProcessStartedEvent event) {

    }

    @Override
    public void beforeProcessCompleted(ProcessCompletedEvent event) {

    }

    @Override
    public void afterProcessCompleted(ProcessCompletedEvent event) {

    }

    @Override
    public void beforeNodeTriggered(ProcessNodeTriggeredEvent event) {

    }

    @Override
    public void afterNodeTriggered(ProcessNodeTriggeredEvent event) {

    }

    @Override
    public void beforeNodeLeft(ProcessNodeLeftEvent event) {

    }

    @Override
    public void afterNodeLeft(ProcessNodeLeftEvent event) {

    }

    @Override
    public void beforeVariableChanged(ProcessVariableChangedEvent event) {

    }

    @Override
    public void afterVariableChanged(ProcessVariableChangedEvent event) {

    }
}

package com.drools.core.listener;

import org.kie.api.event.rule.ObjectDeletedEvent;
import org.kie.api.event.rule.ObjectInsertedEvent;
import org.kie.api.event.rule.ObjectUpdatedEvent;
import org.kie.api.event.rule.RuleRuntimeEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DefaultRuleRuntimeEventListener implements RuleRuntimeEventListener {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void objectInserted(ObjectInsertedEvent event) {
        logger.info("===>>插入对象:{};操作规则:{}", event.getFactHandle(), event.getRule());
    }

    @Override
    public void objectUpdated(ObjectUpdatedEvent event) {
        logger.info("===>>更新对象:{};操作规则:{}", event.getFactHandle(), event.getRule());
    }

    @Override
    public void objectDeleted(ObjectDeletedEvent event) {
        logger.info("===>>删除对象:{};操作规则:{}", event.getFactHandle(), event.getRule());
    }
}


5、将决策表转化成drl字符串

    // 把xls文件解析为String
    public static String getDRL (String realPath) throws FileNotFoundException {
        File file = new File(realPath); // 例如:C:\abc.xls
        InputStream is = new FileInputStream(file);
        SpreadsheetCompiler compiler = new SpreadsheetCompiler();
        String drl = compiler.compile(is, InputType.XLS);
        System.out.println(drl);
        return drl;
    }

顺便分享一个完整的案例,如何从数据库读取脚本,实现动态加载,包括简单的表设计,全量代码:

github-drools+db代码

6、drools部分api使用(这些api是你市面上可能找不到的,一般百度是找不到的哦):
6.1、drl文件中使用函数

package rules

import com.huan.drools.Person

// 定义一个方法,判断用户是否可以玩游戏
function boolean playGameOk(Person person){
    return person.getAge()>=18;
}

// 在when中调用这个函数
function String whenInvoked(Person person){
    return "whenInvoked,peronName:" + person.getName();
}

// 判断用户是否可以玩游戏,主要是为了测试调用drl自定义的函数
rule "rule_can_play_game"
    when
        $person: Person()
        $invokedFunction: String() from whenInvoked($person)
    then
        System.out.println("在when中调用function获取的结果: " + $invokedFunction);
        System.err.println("drl function 判断: 用户:["+$person.getName()+"]是否可以玩游戏?["+playGameOk($person)+"]");
        System.err.println("java static function 调用: "+ String.format("当前用户:%s", $person.getName()));
end

6.2 map在drools的应用

package com.rules
import java.util.Map;
import com.secbro.drools.model.Person;

rule "map-usage"

    agenda-group "map-group"

    when
        $obj : Object();
        $map : Map(["p1"] != $obj);
    then
        System.out.println("p1's age is " + ((Person)$map.get("p1")).getAge());
        System.out.println("p2's age is " + ((Person)$map.get("p2")).getAge());
    end

6.3、全局变量,可以通过这个在drl中 动态的调用 java代码:

package com.rules
import com.secbro.drools.model.Risk
import com.secbro.drools.model.Message

global com.secbro.drools.EmailService emailService

rule "test-global"

agenda-group "test-global-group"

when
then
    Message message = new Message();
    message.setRule(drools.getRule().getName());
    message.setDesc("to send email!");
    emailService.sendEmail(message);
end

6.4、函数的使用:

package com.rules

function String hello(String name){
    return "Hello " + name + "!";
}

rule helloSomeone

    agenda-group "function-group"

    when
        eval(true);
    then
        System.out.println(hello("Tom"));
    end

6.5、可以在规则文件中获取"rule"这个对象,然后可以获取到很多属性:

package com.rules

rule "Get name and package demo"

agenda-group "Name and package"

when
then
    System.out.println("The rule's name is '" + drools.getRule().getName() + "'");
    System.out.println("The rule's package is  '" + drools.getRule().getPackageName() + "'");
end


6.5、query方法,相当于给java提供一个入口,去获取drl文件里面的对象:

package com.rules
import com.secbro.drools.model.Person;

rule "query-test"
    agenda-group "query-test-group1"

    when
        $person : Person()
    then
        System.out.println("The rule query-test fired!");
    end

query "query-1"
    $person : Person(age > 30)
end

query "query-2"(String nameParam)
    $person : Person(age > 30,name == nameParam)
end

package com.secbro.drools.test;

import com.secbro.drools.BaseTest;
import com.secbro.drools.model.Person;
import org.junit.Test;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.QueryResults;
import org.kie.api.runtime.rule.QueryResultsRow;


public class QueryTest extends BaseTest {

    @Test
    public void queryTest() {
        KieSession kieSession = this.getKieSession("query-test-group1");

        Person p1 = new Person();
        p1.setAge(29);
        Person p2 = new Person();
        p2.setAge(40);

        kieSession.insert(p1);
        kieSession.insert(p2);
        int count = kieSession.fireAllRules();
        System.out.println("Fire " +count + " rule(s)!");

        QueryResults results = kieSession.getQueryResults("query-1");
        System.out.println("results size is " + results.size());
        for(QueryResultsRow row : results){
            Person person = (Person) row.get("$person");
            System.out.println("Person from WM, age : " + person.getAge());
        }

        kieSession.dispose();
    }

    @Test
    public void queryWithParamTest() {
        KieSession kieSession = this.getKieSession("query-test-group1");

        Person p1 = new Person();
        p1.setAge(29);
        p1.setName("Ross");
        Person p2 = new Person();
        p2.setAge(40);
        p2.setName("Tom");

        kieSession.insert(p1);
        kieSession.insert(p2);
        int count = kieSession.fireAllRules();
        System.out.println("Fire " +count + " rule(s)!");

        QueryResults results = kieSession.getQueryResults("query-2","Tom");
        System.out.println("results size is " + results.size());
        for(QueryResultsRow row : results){
            Person person = (Person) row.get("$person");
            System.out.println("Person from WM, age : " + person.getAge() + "; name :" + person.getName());
        }

        kieSession.dispose();
    }
}

6.6、同一个对象类型,在drl文件中如何展示:

package com.rules

import com.secbro.drools.model.Customer;

rule "two same objects"
    agenda-group "two same objects"
    when
        $firstCustomer:Customer(age == 59);
        $secondCustomer:Customer(this != $firstCustomer,age == 61);
    then
        System.out.println("firstCustomer age :" + $firstCustomer.getAge());
        System.out.println("secondCustomer age :" + $secondCustomer.getAge());
    end

6.7、drl文件中的from的用法:

package com.rules

import com.secbro.drools.model.Customer;
import java.util.List;

rule "two same objects in list"
    agenda-group "two same objects in list"
    when
        $list : List();
        $firstCustomer:Customer(age == 59) from $list;
        $secondCustomer:Customer(this != $firstCustomer,age == 61) from $list;
    then
        System.out.println("two same objects in list:firstCustomer age :" + $firstCustomer.getAge());
        System.out.println("two same objects in list:secondCustomer age :" + $secondCustomer.getAge());
    end

6.8、Calendar在 drools的使用:设置不同的日期限制,规则中对应的触发日期就不一样,比time更强大一些

package com.secbro.drools.chapter21;

import com.secbro.drools.BaseTest;
import org.junit.Test;
import org.kie.api.runtime.KieSession;
import org.kie.api.time.Calendar;
import org.quartz.impl.calendar.WeeklyCalendar;

public class CalenderTest extends BaseTest{

    @Test
    public void testCalender(){
        KieSession kieSession = this.getKieSessionBySessionName("calenderTest-rules");
        kieSession.getCalendars().set("weekday_exclude",WEEKDAY_EXCLUDE);
        kieSession.getCalendars().set("weekday",WEEKDAY);
        kieSession.fireAllRules();
        kieSession.dispose();

    }

    private static final Calendar WEEKDAY = new Calendar() {
        @Override
        public boolean isTimeIncluded(long timestamp) {
            WeeklyCalendar weeklyCalendar = new WeeklyCalendar();
            weeklyCalendar.setDaysExcluded(new boolean[]{false,false,false,false,false,false,false});
            weeklyCalendar.setDayExcluded(java.util.Calendar.WEDNESDAY,true);
            return weeklyCalendar.isTimeIncluded(timestamp);
        }
    };

    private static final Calendar WEEKDAY_EXCLUDE = new Calendar() {
        @Override
        public boolean isTimeIncluded(long timestamp) {
            WeeklyCalendar weeklyCalendar = new WeeklyCalendar();
            weeklyCalendar.setDaysExcluded(new boolean[]{false,false,false,false,false,false,false});
            return weeklyCalendar.isTimeIncluded(timestamp);
        }
    };

}

package com.calenderTest

rule "test-calender-rule"
calendars "weekday"
when

then
    System.out.println("test-calender-rule 被触发");
end

rule "test-calender-rule-1"
calendars "weekday_exclude"
when

then
    System.out.println("test-calender-rule-1 被触发");
end

6.9、declare 用法:

package com.newType
import java.util.Date;


rule "new-type-rule-1"

when
    $country: Country(name == "美国")
then
    Address address = new Address();
    address.setName(CountryName.CHINA.getFullName());
    address.setCity("北京");
    address.setNumber(100000);
    insert(address);
 end

rule "new-type-rule"

when
    $address : Address(name == CountryName.CHINA.getFullName())
then
    System.out.println("规则被触发");
 end

declare Address extends Country
    number : Integer
    city : String
    crateTime : Date
end

declare Country
    name : String
end

declare enum CountryName
    CHINA("中国");
    fullName : String
end


6.10、meta-元数据:

 declare City
    @author("wmd")
    name : String @key
    address: String
 end

6.11、根据不同的路径读excel决策表:

    @Test
    public void checkDrl() throws FileNotFoundException {
        File file = new File("E:\GitHub\respo\drools-lesson\src\main\resources\decision.xls");
        InputStream is = new FileInputStream(file);
        SpreadsheetCompiler compiler = new SpreadsheetCompiler();
        String drl = compiler.compile(is, InputType.XLS);
        System.out.println(drl);
    }

    @Test
    public void checkDrl2() throws FileNotFoundException {
        SpreadsheetCompiler compiler = new SpreadsheetCompiler();
        String drl = compiler.compile(ResourceFactory.newClassPathResource("com/decision/decision.xls"), InputType.XLS);
        System.out.println(drl);
    }

6.12、如何获取kiebase 如何获取kiesession

package com.secbro2.drools.chapter6;

import org.kie.api.KieServices;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;

import java.util.Collection;
import java.util.List;

public class Chapter6 {
	public static void main(String[] args) {
		KieServices kieServices = KieServices.Factory.get();
		KieContainer container = kieServices.getKieClasspathContainer();
		Results results = container.verify();
		List messages = results.getMessages();
		System.out.println("messages size:" + messages.size());
		for (Message msg : messages) {
			System.out.println("level:" + msg.getLevel() + ";text=" + msg.getText());
		}
		Collection kieBaseNames = container.getKieBaseNames();
		for(String kieBaseName : kieBaseNames){
			System.out.println("kieBaseName----" + kieBaseName);
			Collection kieSessionNamesInKieBase = container.getKieSessionNamesInKieBase(kieBaseName);
			for(String kieSession : kieSessionNamesInKieBase){
				System.out.println("kieSession-----" + kieSession);
			}
		}
	}
}

6.13、如何获取jar里面的规则文件,Drools中提供了一个类KieScanner,可以支持从Maven存储库动态的加载并更新规则。官方给出的例子没有很好的证明这一能力。下面我来演示一下:

package com.secbro2.drools.demo;

import org.kie.api.KieServices;
import org.kie.api.builder.KieScanner;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class Demo8 {
	public static void main(String[] args) throws InterruptedException {
		KieServices kieServices = KieServices.Factory.get();
		KieContainer container = kieServices.newKieContainer(kieServices.newReleaseId("com.secbro2","drools-rules","1.0-SNAPSHOT"));
		KieScanner kieScanner = kieServices.newKieScanner(container);
		kieScanner.start(1000);
		KieSession kieSession = container.newKieSession("all-kieSession-1");
		while (true){
			Thread.sleep(5000);
			int nums = kieSession.fireAllRules();
			System.out.println("Fire " + nums + " rules!");
		}
	}
}

6.14、获取jar包里面的规则,利用ksession动态的获取里面的不同类型的对象,通过过滤器:

package cn.abel.service;

import cn.abel.model.Person;
import org.drools.core.ClassObjectFilter;
import org.kie.api.KieServices;
import org.kie.api.builder.KieScanner;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;


@Service
public class ExecuteService {
    private KieContainer kContainer;
    @PostConstruct
    public void setUp() {
        KieServices ks = KieServices.Factory.get();
        ReleaseId releaseId = ks.newReleaseId("cn.abel", "springboot-drools-dynamic-rules-kjar", "1.0-SNAPSHOT");
        kContainer = ks.newKieContainer(releaseId);
        KieScanner kScanner = ks.newKieScanner(kContainer);
        // Start the KieScanner polling the Maven repository every 10 seconds
        kScanner.start(10000L);
    }

    public Integer execute() {
        KieSession kSession = kContainer.newKieSession("PersonAgeSession");
        kSession.setGlobal("out", System.out);
        kSession.insert(new Person("Dave",100));
        kSession.fireAllRules();
        Integer result = null;
        for (Object per : kSession.getObjects(new ClassObjectFilter(Person.class))) {
            if (((Person) per).getName().equals("abel")) {
                result = ((Person) per).getAge();
            }
        }
        return result;
    }
}

6.15 drt用法,这个,我个人觉得不好用,但是也写下吧

template header
age
type
log

package com.us.templates;

global java.util.List list;

template "cheesefans"

rule "Cheese fans_@{row.rowNumber}"
    when
        Person(age == @{age})
        Cheese(type == "@{type}")
    then
        list.add("@{log}");
end
end template



package com.us.templates;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

import java.util.ArrayList;
import java.util.List;


public class SimpleRuleTemplateExample {

    public static void main(String[] args) {
        KieContainer kc = KieServices.Factory.get().getKieClasspathContainer();
        execute(kc);
    }

    public static void execute(KieContainer kc) {
        KieSession ksession = kc.newKieSession("TemplatesKS");

        //now create some test data
        ksession.insert(new Cheese("stilton",
                42));
        ksession.insert(new Person("michael",
                "stilton",
                42));

//        Young man cheddar
        ksession.insert(new Cheese("cheddar",
                21));
        ksession.insert(new Person("michael",
                "stilton",
                21));
        final List list = new ArrayList();
        ksession.setGlobal("list", list);

        ksession.fireAllRules();

        System.out.println(list);

        ksession.dispose();
    }
}

6.16、创建一个kjar、初始化一个jar,动态加载(这个功能,个人觉得很吊)

package com.secbro2.drools.demo;

import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.conf.EqualityBehaviorOption;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.io.Resource;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


public class DynamicDrlDemo {

	private static final String RULES_FILE_NAME = "rules.drl";

	
	private static final String RULES_PATH = "com";

	
	private static final String RULES = "package com.rulesn" +
			"n" +
			"rule "chapter4"n" +
			"n" +
			"whenn" +
			"n" +
			"thenn" +
			"n" +
			"System.out.println("Fire the default rules for dynamic!");n" +
			"end";


	public static void main(String[] args) {
		KieServices kieServices = KieServices.Factory.get();

		// 指定kjar包
		final ReleaseId releaseId = kieServices.newReleaseId("com.secbro2", "drools-rules", "1.0.0");

		// 创建初始化的kjar
		InternalKieModule kJar = initKieJar(kieServices, releaseId);
		KieRepository repository = kieServices.getRepository();
		repository.addKieModule(kJar);
		KieContainer kieContainer = kieServices.newKieContainer(releaseId);
		KieSession session = kieContainer.newKieSession();

		//同一个fact第一次不命中
		try {
			session.fireAllRules();
		} finally {
			session.dispose();
		}
		System.out.println("-----first fire end-------");

		//新增一个规则文件
		kJar = createKieJar(kieServices, releaseId, new ResourceWrapper(ResourceFactory.newByteArrayResource(RULES.getBytes()), RULES_FILE_NAME));
		repository.addKieModule(kJar);
		kieContainer.updateToVersion(releaseId);

		//同一个fact再次过滤规则:命中
		session = kieContainer.newKieSession();
		try {
			session.fireAllRules();
		} finally {
			session.dispose();
		}
		System.out.println("-----second fire end-------");
	}

	
	private static List getRuleFiles() {
		List list = new ArrayList<>();
		URL url = Thread.currentThread().getContextClassLoader().getResource("");
		if (url == null) {
			return list;
		}
		String filePath = url.getPath();
		File rootDir = new File(filePath);
		File[] files = rootDir.listFiles();
		if (files == null) {
			return list;
		}

		for (File itemFile : files) {
			if (itemFile.isDirectory() && itemFile.getName().equals(RULES_PATH)) {
				File[] childrenFile = itemFile.listFiles();
				if (childrenFile != null) {
					for (File f : childrenFile) {
						if (f.getName().endsWith(".drl")) {
							list.add(f);
						}
					}
				}
			}
		}
		return list;
	}

	
	public static InternalKieModule initKieJar(KieServices ks, ReleaseId releaseId) {
		KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
		kfs.writePomXML(getPom(releaseId));
		for (File file : getRuleFiles()) {
			kfs.write("src/main/resources/" + file.getName(),
					ResourceFactory.newClassPathResource(RULES_PATH + File.separator + file.getName(), "UTF-8"));
		}
		KieBuilder kieBuilder = ks.newKieBuilder(kfs);
		if (!kieBuilder.buildAll().getResults().getMessages().isEmpty()) {
			throw new IllegalStateException("Error creating KieBuilder.");
		}
		return (InternalKieModule) kieBuilder.getKieModule();
	}

	public static InternalKieModule createKieJar(KieServices ks, ReleaseId releaseId, ResourceWrapper resourceWrapper) {
		KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
		kfs.writePomXML(getPom(releaseId));
		kfs.write("src/main/resources/" + resourceWrapper.getTargetResourceName(), resourceWrapper.getResource());
		KieBuilder kieBuilder = ks.newKieBuilder(kfs);
		if (!kieBuilder.getResults().getMessages().isEmpty()) {
			System.out.println(kieBuilder.getResults().getMessages());
			throw new IllegalStateException("Error creating KieBuilder.");
		}
		return (InternalKieModule) kieBuilder.getKieModule();
	}

	
	public static KieFileSystem createKieFileSystemWithKProject(KieServices ks, boolean isDefault) {
		KieModuleModel kproj = ks.newKieModuleModel();
		KieBaseModel kieBaseModel = kproj.newKieBaseModel("KBase").setDefault(isDefault)
				.setEqualsBehavior(EqualityBehaviorOption.EQUALITY).setEventProcessingMode(EventProcessingOption.STREAM);
		// Configure the KieSession.
		kieBaseModel.newKieSessionModel("KSession").setDefault(isDefault)
				.setType(KieSessionModel.KieSessionType.STATEFUL);
		KieFileSystem kfs = ks.newKieFileSystem();
		kfs.writeKModuleXML(kproj.toXML());
		return kfs;
	}

	
	public static String getPom(ReleaseId releaseId, ReleaseId... dependencies) {
		StringBuilder pom = new StringBuilder("n"
				+ "n"
				+ "  4.0.0n" + "n" + "  " + releaseId.getGroupId()
				+ "n" + "  " + releaseId.getArtifactId() + "n" + "  "
				+ releaseId.getVersion() + "n" + "n");
		if (dependencies != null && dependencies.length > 0) {
			pom.append("n");
			for (ReleaseId dep : dependencies) {
				pom.append("n");
				pom.append("  ").append(dep.getGroupId()).append("n");
				pom.append("  ").append(dep.getArtifactId()).append("n");
				pom.append("  ").append(dep.getVersion()).append("n");
				pom.append("n");
			}
			pom.append("n");
		}
		pom.append("");
		return pom.toString();
	}

	static class ResourceWrapper {
		private Resource resource;

		private String targetResourceName;

		public ResourceWrapper(Resource resource, String targetResourceName) {
			this.resource = resource;
			this.targetResourceName = targetResourceName;
		}

		public Resource getResource() {
			return resource;
		}

		public String getTargetResourceName() {
			return targetResourceName;
		}

		public void setResource(Resource resource) {
			this.resource = resource;
		}

		public void setTargetResourceName(String targetResourceName) {
			this.targetResourceName = targetResourceName;
		}
	}
}

决策表长什么样?截图看看

7、drools如何结合 规则流呢?
drools引擎控制规则分组,以及规则执行先后次序的方法有多种。
第一种:salience
第二种:ruleflow-group 如下图:(流程的编写可以使用drools的eclipse插件可视化的完成。)
官网参考地址:http://www.jboss.org/drools/drools-flow

rule "XX"
ruleflow-group "A"
	...
	then
	...
end

注意:第二种比较复杂,结合流程图,可以完成很复杂的商业逻辑:

下面详细聊聊其用法:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/932687.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号