精华内容
下载资源
问答
  • Drools规则引擎

    2018-10-15 15:48:02
    描述Drools规则引擎的相关内容,并讲述java环境下如何集成drools工具实现规则的推理
  • drools规则引擎

    2020-05-14 18:34:46
    drools规则引擎 规则引擎是什么 规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据...

    drools规则引擎

    规则引擎是什么

    规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。

    Drools是一款基于java语言的开源规则引擎,基于RETE算法实现。

    引入规则引擎后带来的好处

    一.实现业务逻辑与业务规则的分离,实现业务规则的集中管理;
    二.可以动态修改业务规则,从而快速响应需求变更;
    三.使业务分析人员也可以参与编辑、维护系统的业务规则;
    四.使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单;

    规则执行流程

    推理机拿到数据和规则后,进行匹配,然后把匹配的规则和数据传递给Agenda。
    在这里插入图片描述
    数据被 assert 进 WorkingMemory 后,和 RuleBase 中的 rule 进行匹配(确切的说应该是 rule 的 LHS ),如果匹配成功这条 rule 连同和它匹配的数据(此时就叫做 Activation )一起被放入 Agenda ,等待 Agenda 来负责安排激发 Activation (其实就是执行 rule 的 RHS ),图中的菱形部分就是在 Agenda 中来执行的, Agenda 就会根据冲突解决策略来安排 Activation 的执行顺序。

    创建入门项目

    1.项目依赖

    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-core</artifactId>
        <version>7.14.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.kie</groupId>
        <artifactId>kie-spring</artifactId>
        <version>7.14.0.Final</version>
    </dependency>
    

    2.创建配置类

    @Configuration
    public class DroolsAutoConfiguration {
        private static final String RULES_PATH = "rules/";
    
        @Bean
        @ConditionalOnMissingBean(KieFileSystem.class)
        public KieFileSystem kieFileSystem() throws IOException {
            KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
            for (Resource file : getRuleFiles()) {
                kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
            }
            return kieFileSystem;
        }
    
        private Resource[] getRuleFiles() throws IOException {
            ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
            return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
        }
    
        @Bean
        @ConditionalOnMissingBean(KieContainer.class)
        public KieContainer kieContainer() throws IOException {
            final KieRepository kieRepository = getKieServices().getRepository();
            kieRepository.addKieModule(new KieModule() {
                public ReleaseId getReleaseId() {
                    return kieRepository.getDefaultReleaseId();
                }
            });
            KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
            kieBuilder.buildAll();
            return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
        }
    
    
        @Bean
        @ConditionalOnMissingBean(KieBase.class)
        public KieBase kieBase() throws IOException {
            return kieContainer().getKieBase();
        }
    
        @Bean
        @ConditionalOnMissingBean(KieSession.class)
        public KieSession kieSession() throws IOException {
            KieSession kieSession = kieContainer().newKieSession();
            return kieSession;
        }
    
        @Bean
        @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)
        public KModuleBeanFactoryPostProcessor kiePostProcessor() {
            return new KModuleBeanFactoryPostProcessor();
        }
        public KieServices getKieServices() {
            System.setProperty("drools.dateformat","yyyy-MM-dd");
            return KieServices.Factory.get();
        }
    }
    

    3.创建drl文件

    Drools的规则文件是以*.drl结尾的文件,我们来看一个最简单的规则文件中都是包含什么。

    通常来说,我们会把规则文件放在resources资源文件夹下,这里呢我们在resources文件夹下新建一个rules文件夹,然后再新建一个HelloWord.drl文件

    package rules;
    import java.lang.String;
    import java.util.List;
    
    rule "hello,word"
        when
            eval(true)
        then
            System.err.println("hello,word!");
    end
    
    1. 规则文件,就是我们新建的这个HelloWord.drl可以理解为一个Java类
    2. package,这个跟Java中的包名是差不多的
    3. import,此文件中需要的类。
    4. rule,可以理解为给这个规则起的一个名字,一个规则文件中可以包含多个rule。
    5. when,when下面可以放置一些条件判断的表达式以及定义一些变量什么的。如果里面内容为空的话则会默认添加一个eval(true)代表一个为true的表达式
    6. then,当when下面的表达式为true是then下方的代码才会执行,在这里可以直接编写Java代码(代码所需要的类通过import引入),当然也可以使用when模块定义的一些变量
    7. end 代表规则hello,word的结束。

    4.Java调用

    新建一个测试类

    @SpringBootTest
    @WebAppConfiguration
    class DroolsApplicationTests {
    
        @Autowired
        KieSession kieSession;
    }
    

    测试方法

        @Test
        void contextLoads() {
            kieSession.fireAllRules();
        }
    

    kieSession.fireAllRules方法是执行所有的规则,在运行了这个测试方法之后我们应该就可以看到控制台打印的一句hello,word!了

    drools语法

    1.关键字

    • Hard keywords(Cannot use any):
      true,false,null
    • Soft keywords(avoid use)
      lock-on-active date-effective date-expires no-loop auto-focus activation-group agenda-group ruleflow-group entry-point duration package import dialect salience enabled attributes rule extend when then template query declare function global eval not in or and exists forall accumulate collect from action reverse result end over init

    2.注释

    • 单行注释
      // this is a single line comment
    • 多行注释
      /* this is a multi-line comment
      in the left hand side of a rule */

    3.Pakage

    • package
      package表示一个命名空间.package是必须定义的,必须放在规则文件第一行.

    • import
      import语句的工作方式类似于Java中的import语句。您需要为要在规则中使用的任何对象指定完全限定路径和类型名称。

    • global
      global用于定义全局变量。
      Rules:

      global java.util.List myGlobalList;
      
      rule "Using a global"
      when
        eval( true )
      then
        myGlobalList.add( "Hello World" );
      end
      

      设置 global value:

      List list = new ArrayList();
      KieSession kieSession = kiebase.newKieSession();
      kieSession.setGlobal( "myGlobalList", list );
      

    4.Function

    • function
      function是一种将语义代码放置在规则源文件中的方法,而不是普通的Java类

      function String hello(String name) {
        return "Hello "+name+"!";
      }
      import function my.package.Foo.hello
      rule "using a static function"
      when
        eval( true )
      then
        System.out.println( hello( "Bob" ) );
      end
      

    5.Query

    • query
      query是一种搜索工作内存中与指定条件匹配的事实的简单方法.

      对所有30岁以上的人的简单查询
      query "people over the age of 30"
        person : Person( age > 30 )
      end
      
      查询超过x岁的人,以及居住在y的人
      query "people over the age of x"  (int x, String y)
        person : Person( age > x, location == y )
      end
      
      QueryResults results = ksession.getQueryResults( "people over the age of 30" );
      System.out.println( "we have " + results.size() + " people over the age  of 30" );
      
      System.out.println( "These people are are over 30:" );
      
      for ( QueryResultsRow row : results ) {
        Person person = ( Person ) row.get( "person" );
        System.out.println( person.getName() + "\n" );
      }
      

    6.Rule

    rule定义规则。rule “ruleName”。

    一个规则可以包含三个部分:属性部分,条件部分:即LHS,结果部分:即RHS.
    1.属性
    定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等。
    activation-group agenda-group auto-focus date-effective date-expires dialect duration duration-value enabled lock-on-active no-loop ruleflow-group salience

    • no-loop
      默认值:false

      类型:Boolean

      在一个规则当中如果条件满足就对Working Memory当中的某个Fact对象进行了修改,比如使用update 将其更新到当前的Working Memory当中,这时引擎会再次检查所有的规则是否满足条件,如果满足会再次执行.

    • ruleflow-group
      默认值:N/A

      类型:String

      Ruleflow是一个Drools功能,可让您控制规则的触发。由相同的规则流组标识汇编的规则仅在其组处于活动状态时触发。将规则划分为一个个的组,然后在规则流当中通过使用ruleflow-group属性的值,从而使用对应的规则。

    • lock-on-active
      默认值:false

      类型:Boolean

      当在规则上使用ruleflow-group 属性或agenda-group 属性的时候,将lock-on-action 属性的值设置为true,可能避免因某些Fact 对象被修改而使已经执行过的规则再次被激活执行。可以看出该属性与no-loop 属性有相似之处,no-loop 属性是为了避免Fact 修改或调用了insert、retract、update 之类而导致规则再次激活执行,这里的lock-on-action 属性也是起这个作用,lock-on-active 是no-loop 的增强版属性,它主要作用在使用ruleflow-group 属性或agenda-group 属性的时候

    • salience
      默认值:0

      类型:integer

      设置规则执行的优先级,salience 属性的值是一个数字,数字越大执行优先级越高,同时它的值可以是一个负数.
      规则的salience 默认值为0,所以如果我们不手动设置规则的salience 属性,那么它的执行顺序是随机的.

    • agenda-group
      默认值:MAIN

      类型:String

      规则的调用与执行是通过StatelessSession 或StatefulSession 来实现的,一般的顺序是创建一个StatelessSession 或StatefulSession,将各种经过编译的规则的package 添加到session当中,接下来将规则当中可能用到的Global对象和Fact对象插入到Session 当中,最后调用fireAllRules 方法来触发、执行规则。在没有调用最后一步fireAllRules方法之前,所有的规则及插入的Fact对象都存放在一个名叫Agenda表的对象当中,这个Agenda表中每一个规则及与其匹配相关业务数据叫做Activation,在调用fireAllRules方法后,这些Activation 会依次执行,这些位于Agenda 表中的Activation 的执行顺序在没有设置相关用来控制顺序的属性时(比如salience 属性),它的执行顺序是随机的,不确定的。Agenda Group 是用来在Agenda 的基础之上,对现在的规则进行再次分组,具体的分组方法可以采用为规则添加agenda-group属性来实现。agenda-group 属性的值也是一个字符串,通过这个字符串,可以将规则分为若干个Agenda Group,默认情况下,引擎在调用这些设置了agenda-group 属性的规则的时候需要显示的指定某个Agenda Group 得到Focus(焦点),这样位于该Agenda Group 当中的规则才会触发执行,否则将不执行。

    • auto-focus
      默认值:false

      类型:Boolean

      用来在已设置了agenda-group的规则上设置该规则是否可以自动独取Focus,如果该属性设置为true,那么在引擎执行时,就不需要显示的为某个Agenda Group设置Focus,否则需要。对于规则的执行的控制,还可以使用Agenda Filter 来实现。在Drools 当中,提供了一个名为org.drools.runtime.rule.AgendaFilter 的Agenda Filter 接口,用户可以实现该接口,通过规则当中的某些属性来控制规则要不要执行。org.drools.runtime.rule.AgendaFilter 接口只有一个方法需要实现,方法体如下: public boolean accept(Activation activation); 在该方法当中提供了一个Activation 参数,通过该参数我们可以得到当前正在执行的规则对象或其它一些属性,该方法要返回一个布尔值,该布尔值就决定了要不要执行当前这个规则,返回true 就执行规则,否则就不执行。

    • activation-group
      默认值:N/A

      类型:String

      该属性的作用是将若干个规则划分成一个组,用一个字符串来给这个组命名,这样在执行的时候,具有相同activation-group属性的规则中只要有一个会被执行,其它的规则都将不再执行。也就是说,在一组具有相同activation-group属性的规则当中,只有一个规则会被执行,其它规则都将不会被执行。当然对于具有相同activation-group属性的规则当中究竟哪一个会先执行,则可以用类似salience之类属性来实现。

    • dialect
      默认值: 根据package指定

      类型:String,”java” or “mvel”

      dialect种类是用于LHS或RHS代码块中的任何代码表达式的语言。目前有两种dialect,Java和MVEL。虽然dialect可以在包级别指定,但此属性允许为规则覆盖包定义。

    • date-effective
      默认值:N/A

      类型:字符串,包含日期和时间定义。格式:dd-MMM-yyyy(25-Sep-2009).

      仅当当前日期和时间在日期有效属性后面时,才能激活规则。

    • date-expires
      默认值:N/A

      类型:字符串,包含日期和时间定义。格式:dd-MMM-yyyy(25-Sep-2009).

      如果当前日期和时间在date-expires属性之后,则无法激活规则.

    • enabled
      默认值:false

      类型:String

      表示规则是可用的,如果手工为一个规则添加一个enabled属性,并且设置其enabled属性值为false,那么引擎就不会执行该规则.

    • duration
      默认值:无

      类型:long

      持续时间指示规则将在指定的持续时间之后触发,如果它仍然是true.

    2.条件LHS
    定义当前规则的条件,如when Message(); 判断当前workingMemory中是否存在Message对象。

    Left Hand Side(LHS)是规则的条件部分的公共名称。它由零个或多个条件元素组成。
    如果LHS为空,它将被认为是一个条件元素,它总是为真,并且当创建一个新的WorkingMemory会话时,它将被激活一次。
    “`
    Conditions / LHS —匹配模式(Patterns)

      没有字段约束的Pattern
      Person()
    
      有文本字段约束的Pattern
      Person( name == “bob” )
    
      字段绑定的Pattern
      Person( $name : name == “bob” )
      变量名称可以是任何合法的java变量,$是可选的,可由于区分字段和变量
    
      Fact绑定的Pattern
      $bob : Person( name == “bob” )字段绑定的Pattern
    
      变量约束的Pattern
      Person( name == $name )
    
    

    Drools提供了十二种类型比较操作符:

    > >= < <= == != contains not contains memberOf not memberOf matches not matches
    
    • contains / not contains
      运算符contains用于检查作为Collection或elements的字段是否包含指定的值.

      Cheese( name contains “tilto” )
      Person( fullName contains “Jr” )
      String( this contains “foo” )

    • memberOf / not memberOf
      运算符memberOf用于检查字段是否是集合的成员或元素;该集合必须是一个变量。

      CheeseCounter( cheese memberOf $matureCheeses )

    • matches / not matches
      正则表达式匹配,与java不同的是,不用考虑’/’的转义问题

      Cheese( type matches “(Buffalo)?\S*Mozarella” )

    • exists
      存在。检查Working Memory是否存在某物。使用模式exists,则规则将只激活最多一次,而不管在工作存储器中存在与存在模式中的条件匹配的数据量

    • not
      不存在,检查工作存储器中是否存在某物。认为“not”意味着“there must be none of…”。

    3.结果RHS
    这里可以写普通java代码,即当前规则条件满足后执行的操作,可以直接调用Fact对象的方法来操作应用。

    Right Hand Side(RHS)是规则的结果或动作部分的通用名称;此部分应包含要执行的操作的列表。在规则的RHS中使用命令式或条件式代码是不好的做法;作为一个规则应该是原子的性质 - “when this, then do this”,而不是“when this, maybe do this”。规则的RHS部分也应该保持较小,从而保持声明性和可读性。如果你发现你需要在RHS中的命令式和/或条件代码,那么也许你应该把这个规则分成多个规则。 RHS的主要目的是插入,删除或修改工作存储器数据。为了协助,有一些方便的方法可以用来修改工作记忆;而不必首先引用工作内存实例。

    • update
      更新,告诉引擎对象已经改变(已经绑定到LHS上的某个东西),并且规则可能需要重新考虑。

    • insert(new Something())
      插入,往当前workingMemory中插入一个新的Fact对象,会触发规则的再次执行,除非使用no-loop限定;

    • insertLogical(new Something())
      类似于insert,但是当没有更多的facts支持当前触发规则的真实性时,对象将被自动删除。

    • modify
      修改,与update语法不同,结果都是更新操作。该语言扩展提供了一种结构化的方法来更新事实。它将更新操作与一些setter调用相结合来更改对象的字段。

    • retract
      删除

    系统内置method

    • drools.halt()
      调用drools.halt()立即终止规则执行。这是需要将控制权返回到当前会话使用fireUntilHalt()的点。
    • drools.getWorkingMemory()
      返回WorkingMemory对象.
    • drools.setFocus( String s)
      将焦点设置为指定的agenda group.
    • drools.getRule().getName()
      从规则的RHS调用,返回规则的名称。
    • drools.getTuple()
      返回与当前执行的规则匹配的Tuple,而drools.getActivation()传递相应的激活。
    展开全文
  • 在项目技术选型的过程中,尝试使用了Drools规则引擎。让它来作为项目中有关模式分析和关键词匹配的任务。但后来,因为某种原因,还是撇开了Drools。现将这个过程中使用Drools的一些经验和心得记录下来。(一)什么时候...

    前一段时间在开发了一个做文本分析的项目。在项目技术选型的过程中,尝试使用了Drools规则引擎。让它来作为项目中有关模式分析和关键词匹配的任务。但后来,因为某种原因,还是撇开了Drools。现将这个过程中使用Drools的一些经验和心得记录下来。

    (一)什么时候应该使用规则引擎

    这实际是一个技术选型的问题。但这个问题又似乎是一个很关键的问题(一旦返工的话,你就知道这个问题是多么重要了)。不知大家有没有过这样的经验和体会。往往在项目开始的时候,总会遇到应该选用什么技术?是不是应该使用最新的技术?或者应该选用什么技术呢(PS:现在计算机软件中的各种技术层出不穷,具有类似功能的技术很多)?

    不管怎么样,这些问题总会困扰着我。比如,这次的这个项目。项目要求是要在一些log文件中(这些log文件都是很大的应用系统所产生的,但由于legacy的原因,log本身的维护和规范工作一直没有得到改善,所以想借助于一些外部应用对这些log做以分析和清洗)抽取出有用的信息。

    于是,第一个想到的就是,这是一个文本挖掘类的项目。但又想,要抽取有用信息,必须得建立一些规则或pattern(模式)。所以,我第一个想到了规则引擎。因为这里面要建立好多规则,而这些规则可以独立于代码级别(放到一个单独的drl文件里)并可以用规则引擎去解析和执行。另一个重要的原因是,我原来用过,比较熟悉。这样,也可以节省开发时间吧。于是,好不犹豫的就开始做了Demo....

    但事实上,在经历了一个多星期的编码、测试后,我发现运用规则引擎实在是太笨拙了。

    (1)首先必须建立一些数据模型。通过这些模型来refer规则文件中的LHS和Action。

    (2)还要考虑规则的conflict。如果有一些规则同时被触发,就要考虑设定规则的优先级或者是设定activiation-group来保证在一个group中的规则只有一个规则可以被触发。

    (3)对于‘流’规则group

    ruleflow-group的使用。如果要控制在workingmemory中的规则被触发的顺序,则可以将这些规则分组。然后,通过规则建模的方式来实现。但这也添加了一定的effort。修改或者更新不大方便。

    所以,基于上述体会,我更认为规则引擎更适用于那些对非流程性规则匹配的应用。当然,Drools也支持对流程性规则的建模过程。但,这也许不是最好的方式。

    (二)Drools规则引擎的使用杂记

    (1)Fact

    的变更监听。在Drools里,如果一个Fact通过规则而改变,则需将这种改变通知给规则引擎。这里,一般有两种方式:显式和隐式。

    显式---在drl文件中通过

    update、modify来通知;在程序中,通过Fact的引用调用modifyObject等方法来实现。

    隐式---通过在java bean实现property Listener

    Interface来让引擎自动监听到属性值的变化。我更习惯于这种方式。因为,一般看来凡是在规则引擎中添加到fact都是希望引擎来帮你进行管理的。

    所以,那它自己看到fact的变化是种很省事的办法。也很简单,就是用java bean property

    监听的方式。

    通过StatefulSession来注册。

    调用StatefulSession的某个instance

    的insert(Object,true)实现。而这个object是一个java

    bean。其中,要实现private

    final PropertyChangeSupport changes = new PropertyChangeSupport(

    this );

    public void

    addPropertyChangeListener(final PropertyChangeListener l)

    {

    this.changes.addPropertyChangeListener( l );

    }

    public void

    removePropertyChangeListener(final PropertyChangeListener l)

    {

    this.changes.removePropertyChangeListener( l );

    }

    然后在set方法中调用

    this.changes.firePropertyChange( "temp",null,this.temp

    );

    (2)规则触发的优先级、组设置往往,在设计我们自己的规则时,要考虑规则的触发条件。这不仅限于LHS的条件部分,还有规则本身被触发的有些设置等等。这里,列出一些比较常用和有效的规则优先级设置方式,以及需要注意的地方。

    A.通过Salience方式。此值可正可负。越大优先级越高,也会被引擎首先执行。

    B.通过ruleflow-group 方式。实际上,使用这种方式也就是在使用建立规则流的方式。在Eclipse 3.3

    中,Drools提供了建立规则流的插件。要在drl的同级目录中建立rf和rfm两个文件(当然,插件会帮助你建立这些)。

    选择RuleFlow File。

    这里,需要注意的一点是要在启动规则引擎的时候,加入启动rule flow的代码。

    InputStreamReader source = new

    InputStreamReader(RuleManager.class

    .getResourceAsStream(rule_path));

    PackageBuilder builder = new PackageBuilder();

    builder.addPackageFromDrl(source);

    builder.addRuleFlow(new

    InputStreamReader(RuleManager.class

    .getResourceAsStream(rule_flow_path)));

    Package

    pkg = builder.getPackage();

    RuleBase ruleBase = RuleBaseFactory.newRuleBase();

    ruleBase.addPackage(pkg);

    然后,在每次启动规则引擎的时候,调用如下方法:

    StatefulSession ss;

    ss.startProcess(flowProgress);

    ss.fireAllRules();

    flowProgress 是一个string类型。这个flow的名字。

    这个rule flow图中,显示了一个简单的规则流。如RSA就是一个rule-flow的名字。在这个rule

    set中可以设定一组rules。这样,就可以分开规则执行的顺序。在于rf和rfm同名的另一个 drl文件中定义这些组的名字。通过关键字

    ruleflow-group 来表明。

    C.通过activation-group的方式。通过这种方式,可以exclude一组rule中一旦有一个rule被invoke,而其它rule不

    会被execute。同时,可以搭配使用salience关键字来标明每个rule的优先级,这样就能够使得你想要的一般性概念的rule先被匹配执行。

    D.在使用ruleflow-group 的时候要注意使用lock-on-active true

    关键字在每个rule。这样可以避免一旦有rule被触发,不会造成循环匹配执行。

    E.如果在LHS部分,需要调用某个方法来返回真、假值作为判断的一个条件,那么可以用eval函数。

    如,eval_r(pattern.matched(5,$line.getCurrLine()))

    其中,pattern是某个加入到workingmemory中的一个实例。matched是这个实例所代表类的一个方法。它返回boolean类型。

    (3)Drools规则引擎的使用感受总之,Drools还是一个很不错的开源规则引擎。

    现在v4.0以上的版本已经比以前的版本在速度上有了很大的提升。可以作为我们一般应用程序系统的中间件产品(那些规则不是很经常改变的系统,已经非流程

    类规则)。但是,这其中还是需要一些额外的effort来学习它的使用文档以及整体架构,有一定的学习曲线。

    最后,我想一个较好的对于技术使用的practice就是:首先知道它能为你做什么,它最好的应用领域,然后再去深入。

    展开全文
  • Drools 规则引擎

    2019-01-22 14:37:00
    Drools - Drools - Business Rules Management System (Java™, Open Source) ...[Drools]JAVA规则引擎 -- Drools - quzishen的专栏 - CSDN博客https://blog.csdn.net/quzishen/article/details/6163012 转载于...

    Drools - Drools - Business Rules Management System (Java™, Open Source)

    http://drools.org/

    [Drools]JAVA规则引擎 -- Drools - quzishen的专栏 - CSDN博客
    https://blog.csdn.net/quzishen/article/details/6163012

    转载于:https://www.cnblogs.com/rgqancy/p/10303737.html

    展开全文
  • 最近项目需要增加风控系统,在经过一番调研以后决定使用Drools规则引擎。因为项目是基于SpringCloud的架构,所以此次学习使用了SpringBoot2.0版本结合Drools7.14.0.Final版本。引入依赖<dependency> <...
    f3db283201197676430010694b80d48e.gif学习更多Java干货,戳上面的蓝色字题关注我!

    最近项目需要增加风控系统,在经过一番调研以后决定使用Drools规则引擎。因为项目是基于SpringCloud的架构,所以此次学习使用了SpringBoot2.0版本结合Drools7.14.0.Final版本。

    引入依赖

    <dependency>    <groupId>org.droolsgroupId>    <artifactId>drools-coreartifactId>    <version>7.14.0.Finalversion>dependency><dependency>    <groupId>org.kiegroupId>    <artifactId>kie-springartifactId>    <version>7.14.0.Finalversion>dependency>

    创建配置类

    @Configurationpublic class DroolsAutoConfiguration {    private static final String RULES_PATH = "rules/";    @Bean    @ConditionalOnMissingBean(KieFileSystem.class)    public KieFileSystem kieFileSystem() throws IOException {        KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();        for (Resource file : getRuleFiles()) {            kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));        }        return kieFileSystem;    }    private Resource[] getRuleFiles() throws IOException {        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();        return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");    }    @Bean    @ConditionalOnMissingBean(KieContainer.class)    public KieContainer kieContainer() throws IOException {        final KieRepository kieRepository = getKieServices().getRepository();        kieRepository.addKieModule(new KieModule() {            public ReleaseId getReleaseId() {                return kieRepository.getDefaultReleaseId();            }        });        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());        kieBuilder.buildAll();        return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());    }    @Bean    @ConditionalOnMissingBean(KieBase.class)    public KieBase kieBase() throws IOException {        return kieContainer().getKieBase();    }    @Bean    @ConditionalOnMissingBean(KieSession.class)    public KieSession kieSession() throws IOException {        KieSession kieSession = kieContainer().newKieSession();        return kieSession;    }    @Bean    @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)    public KModuleBeanFactoryPostProcessor kiePostProcessor() {        return new KModuleBeanFactoryPostProcessor();    }    public KieServices getKieServices() {        System.setProperty("drools.dateformat","yyyy-MM-dd");        return KieServices.Factory.get();    }}

    在这个时候我们的基本环境已经搭建好了,接下来我们一起来学习Drools吧

    HelloWord

    程序员的世界里,我们学习任何一门语言都是以HelloWord开启的,本次学习也不例外。

    1.创建规则文件

    Drools的规则文件是以*.drl结尾的文件,我们来看一个最简单的规则文件中都是包含什么。

    通常来说,我们会把规则文件放在resources资源文件夹下,这里呢我们在resources文件夹下新建一个rules文件夹,然后再新建一个HelloWord.drl文件

    package rules;import cn.org.zhixiang.entity.User;import java.lang.String;import java.util.List;rule "hello,word"    when        eval(true)    then        System.err.println("hello,word!");end
    1. 规则文件,就是我们新建的这个HelloWord.drl可以理解为一个Java类

    2. package,这个跟Java中的包名是差不多的

    3. import,此文件中需要的类。

    4. rule,可以理解为给这个规则起的一个名字,一个规则文件中可以包含多个rule。

    5. when,when下面可以放置一些条件判断的表达式以及定义一些变量什么的。如果里面内容为空的话则会默认添加一个eval(true)代表一个为true的表达式

    6. then,当when下面的表达式为true是then下方的代码才会执行,在这里可以直接编写Java代码(代码所需要的类通过import引入),当然也可以使用when模块定义的一些变量

    7. end 代表规则hello,word的结束。

    2.Java调用

    现在我们的规则文件写好以后就可以在Java中来进行调用了。

    1. 新建一个测试类DroolsApplicationHelloWordTests

    @RunWith(SpringRunner.class)@SpringBootTestpublic class DroolsApplicationHelloWordTests {    @Autowired    KieSession kieSession;}

    上方注入的kieSession对象就是以后与Drools打交道最常用的一个对象了,通过它可以直接操作在配置类kieFileSystem方法中加载的所有的规则文件

    2. 编写测试代码

    @Testpublic void testHelloWord() {    kieSession.fireAllRules();}

    kieSession.fireAllRules方法是执行所有的规则,在运行了这个测试方法之后我们应该就可以看到控制台打印的一句hello,word!了

    基础学习

    1. 向规则文件传参

    1. 在entity包下新增一个User的实体类

    public class User {    private String name;    private int age;    public User(String name, int age) {        this.name = name;        this.age = age;    }    //省略getter,setter}

    2. 在hello,word规则下方再次新建一个规则user

    rule "user"    when      $u:User(name=="张三",age==18)    then        $u.setName("李四");        System.err.println("hello,word:"+$u.getName());end

    $u:User(name==“张三”,age==18)的意思就是当存在一个user对象,并且它的name属性等于张三age等于18时就把这个对象赋值给$u。

    在下方的then模块,如果上方的条件成立时就把$u的name属性更新一下,然后打印。

    3. 编写测试代码

    @Testpublic void testUser() {    User user=new User("张三",18);    kieSession.insert(user);    kieSession.fireAllRules();    System.err.println("规则执行完毕后张三变为了:"+user.getName());}

    我们可以使用kieSession.insert方法向规则文件中传参,然后在调用方法后你会发现在规则文件中更改的值在Java代码中也被更改了。

    4. 存在的小问题

    可能你会发现上方代码执行的时候连那句helloword也打印了,为什么呢,这是因为HelloWord那条规则没有验证条件再加上kieSession.fireAllRules()本来就是执行所有被加载的规则的。那么避免这种情况的办法就是执定本次执行的规则

    @Test    public void testOneRule() {        User user=new User("张三",18);        kieSession.insert(user);        kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("user"));    }

    上方的user就是指定的本次执行的规则名称了。

    5.扩展操作

    上方我们通过RuleNameEndsWithAgendaFilter对象成功指定了需要执行的规则文件,其实通过查看此对象的源码我们发现这个对象是AgendaFilter的一个实现类,决定执不执行一个规则的条件是accept方法返回的boolean值决定的。
    所以说如果我们希望可以一次批量匹配多个规则的话可以通过继承AgendaFilter重写accept方法哦

    2. 常用运算符

    1. 连接符

    Drools中存在的三种连接符,上方的代码中我们已经使用过一个了,那就$u:User(name==“张三”,age==18)中的逗号,这里的逗号其实就是and的意思。另外的两个运算符就是&&和||,相信它们两个的意思不用我来介绍了吧。

    不过有一点需要注意的是&&和|| 和逗号,不能同时出现。要不你选择用&&和||要不就只用逗号, 。

    2. 类型比较操作符

    1.首先就是,==,!=,>=,<=这六个

    它们是配合eval使用的,比如上方我们使用的eval(true)就是直接返回的true。当我们比较常量时可以使用eval(u.age>b.age)

    2. contains not contains

    contains用于判断对象的某个字段是否包含另外一个对象

    rule "contains"    when      $s:String()      $u:User(name contains $s)    then        System.err.println("用户张三存在");end
    @Test    public void testContains() {       String name="张三";        User user=new User("张三",18);        kieSession.insert(name);        kieSession.insert(user);        kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("contains"));    }

    not contains顾明思议就是不包含

    3. memberOf not memberOf

    memberOf用于判断对象的某个字段是否存在一个集合中

    rule "memberOf"    when      $list:List()      $u:User(name memberOf $list)    then        System.err.println("用户李四存在");end
    @Test    public void testMemberOf() {        List list=new ArrayList();        list.add("张三");        list.add("李四");        User user=new User("李四",18);        kieSession.insert(list);        kieSession.insert(user);        kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("memberOf"));    }

    not memberOf顾明思议就是不存在

    3. matches not matches

    matches就是用于匹配正则表达式的了

    rule "matches"    when      $u:User(name matches "张.*")    then        System.err.println("用户张xx存在");end
    @Test   public void testMatches() {       User user=new User("张三",18);       kieSession.insert(user);       kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("matches"));   }

    not matches不用我说了吧

     

    点击下方“阅读原文”查看源码!!!

    展开全文
  • 一、关于 drools 规则引擎前面写过一篇 Drools 规则引擎相关的文章,这篇文章主要记录一下规则引擎的环境搭建和简单示例。不熟悉 drools 的朋友可以看看这篇文章: 自己写个 Drools 文件语法检查工具——栈的应用之...
  • Drools规则引擎介绍

    2019-06-26 15:16:18
    Drools规则引擎介绍
  • drools 规则引擎

    2017-10-23 16:57:01
    Drools基本语法: 传递进去数据,用于规则的检查,调用外部接口,同时还可能需要获取到规则执行完毕后 得到的结果。 在drools中,这个传递数据进去的对象,术语叫Fact对象,Fact对象是一个普通的java bean 规则中...
  • 本套餐涵盖三套课程,包含以下内容: (1)Drools规则引擎基础语法使用及实例 (2)Drools规则引擎进阶语法使用及实例 (3)Drools官方提供的规则管理平台Workbench、KIE Server的使用,以及业务系统如何调用等功能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,570
精华内容 1,028
关键字:

drools规则引擎