IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> drools详解 -> 正文阅读

[Java知识库]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;

/**  
 * @Description:将下面的两给drl字符串,其实可以放进数据库中,或者有专门的机制来维护这个字符串,
 * 后面直接读取这个字符串(其实就是drl文件),那么就可以实现动态加载了,缺点是,偏技术,业务人员看不懂
 * @Author: wumingdu
 * @Date: 2022/5/26 13:38
 */
public class DdLoadTest {
	public static void main(String[] args) {
		//rule,rule2可以放在数据库中,有个唯一code和他们对于,代码要执行规则的时候,根据code从数据库获取出来就OK了,这样自己开发的规则管理系统那边对数据库里的规则进行维护就行了
		String rule = "package com.neo.drools\r\n";
		rule += "import com.neo.drools.model.Message;\r\n";
		rule += "rule \"rule1\"\r\n";
		rule += "\twhen\r\n";
		rule += "Message( status == 1, myMessage : msg )";
		rule += "\tthen\r\n";
		rule += "\t\tSystem.out.println( 1+\":\"+myMessage );\r\n";
		rule += "end\r\n";


		String rule2 = "package com.neo.drools\r\n";
		rule += "import com.neo.drools.model.Message;\r\n";

		rule += "rule \"rule2\"\r\n";
		rule += "\twhen\r\n";
		rule += "Message( status == 2, myMessage : msg )";
		rule += "\tthen\r\n";
		rule += "\t\tSystem.out.println( 2+\":\"+myMessage );\r\n";
		rule += "end\r\n";


		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文件,将其动态的转换成字符串,这段代码很牛掰

	/**
     * 规则文件,决策表解析成字符串
     * @param realPath  决策表路径
     * @return  字符串
     */
    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 <a href="mailto:312182539@qq.com">fbf</a>
        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;";
    }



	/**
     * 读取drl文件
     */
    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,最终会变解析为字符串
	//这个字符串是需要被解析运行的,如下:
	
	/**
     * 把字符串解析成KieSession
     * @param drl   规则文件字符串
     * @return  KieSession
     */
    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<Message> 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;

/**
 * @author <a href="mailto:hongwen0928@outlook.com">Karas</a>
 * @date 2020/9/9
 * @since 7.37.0.Final
 */
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;

/**
 * @author <a href="mailto:hongwen0928@outlook.com">Karas</a>
 * @date 2020/9/9
 * @since 7.37.0.Final
 */
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;

/**
 * @author <a href="mailto:hongwen0928@outlook.com">Karas</a>
 * @date 2020/9/9
 * @since 7.37.0.Final
 */
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;

/**
 * Created by zhuzs on 2017/8/20.
 */
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;
/**
 * @author zzs
 */
public class Chapter6 {
	public static void main(String[] args) {
		KieServices kieServices = KieServices.Factory.get();
		KieContainer container = kieServices.getKieClasspathContainer();
		Results results = container.verify();
		List<Message> messages = results.getMessages();
		System.out.println("messages size:" + messages.size());
		for (Message msg : messages) {
			System.out.println("level:" + msg.getLevel() + ";text=" + msg.getText());
		}
		Collection<String> kieBaseNames = container.getKieBaseNames();
		for(String kieBaseName : kieBaseNames){
			System.out.println("kieBaseName----" + kieBaseName);
			Collection<String> 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;
/**
 * @author zzs
 */
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;

/**  
 * @Description:
 * @Author: wumingdu
 * @Date: 2022/5/27 10:23
 */
@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

在这里插入图片描述
在这里插入图片描述

/*
 * Copyright 2010 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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;

/**
 * @author  yyb
 */
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<String> list = new ArrayList<String>();
        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;

/**
 * @author zzs
 */
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.rules\n" +
			"\n" +
			"rule \"chapter4\"\n" +
			"\n" +
			"when\n" +
			"\n" +
			"then\n" +
			"\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<File> getRuleFiles() {
		List<File> 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;
	}

	/**
	 * 初始化一个kjar:把原有的drl包含进新建的kjar中
	 *
	 * @param ks
	 * @param releaseId
	 */
	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();
	}

	/**
	 * 创建默认的kbase和stateful的kiesession
	 *
	 * @param ks
	 * @param isDefault
	 * @return
	 */
	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;
	}

	/**
	 * 创建kjar的pom
	 *
	 * @param releaseId    maven
	 * @param dependencies 依赖
	 * @return
	 */
	public static String getPom(ReleaseId releaseId, ReleaseId... dependencies) {
		StringBuilder pom = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
				+ "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
				+ "         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n"
				+ "  <modelVersion>4.0.0</modelVersion>\n" + "\n" + "  <groupId>" + releaseId.getGroupId()
				+ "</groupId>\n" + "  <artifactId>" + releaseId.getArtifactId() + "</artifactId>\n" + "  <version>"
				+ releaseId.getVersion() + "</version>\n" + "\n");
		if (dependencies != null && dependencies.length > 0) {
			pom.append("<dependencies>\n");
			for (ReleaseId dep : dependencies) {
				pom.append("<dependency>\n");
				pom.append("  <groupId>").append(dep.getGroupId()).append("</groupId>\n");
				pom.append("  <artifactId>").append(dep.getArtifactId()).append("</artifactId>\n");
				pom.append("  <version>").append(dep.getVersion()).append("</version>\n");
				pom.append("</dependency>\n");
			}
			pom.append("</dependencies>\n");
		}
		pom.append("</project>");
		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

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

下面详细聊聊其用法:

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-01 15:02:20  更:2022-06-01 15:07:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:29:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码