Drools一个很好的例子

转自http://www.360doc.com/content/15/0701/15/5054188_481943680.shtml

一、问题描述

 

假设雇员 Employ 有:

           学历信息 eduInfo , 简历信息 resume ,

           考核信息 annualExam 和奖惩信息  awardPunish ;

要确定其:

           基本工资 basicSalary ,职务工资 dutySalary ,

           分红金额 bonus 和 总工资 totalSalary .

 

规则如下:

【 1 】学历决定基本工资( basicSalary ):

                       ====> 本科 1500 研究生 2500

【 2 】简历决定职务工资 (dutySalary) :

                       ====> 技术 2000 管理 4500

【 3 】年度考核决定分红 (bonus) :

                       ====> 分红总金额 1000

                       ==> 考核结果:

                        ==> 优秀 100% ( 1000 );良好 90% ( 900 );

                                       合格 60% ( 600 ); 不合格 0% ( 0 );

【 4 】奖惩决定计算最终工资与【 123 】项工资之和的比例:

                       ====> 奖励: * 110% ( +10% )

                       ====> 惩罚: * 90% ( -10% )

                       ====> 无: * 100% ( 0% )

【 5 】计算总工资: (【 1 】 + 【 2 】 + 【 3 】) * 【 4 】

 

二、问题分析

 

1. 基本流程:

 

P 【计算基本工资,计算职务工资,计算分红, 计算奖惩比例】

                    ====> 计算总工资 ( 根据奖惩情况 )

其中, P[i,...,k] 表示任务 i,...,k 并发执行, ====> 表示顺序执行。

即有: P[1,2,3, 4] ===> 5

 

三、概要设计

 

【 1 】类 Employ 的设计:

【 2 】规则文件的编写和组织:

                ==> 学历规则文件: EduInfoRule.drl

                ==> 简历规则文件: ResumeRule.drl

                ==> 分红规则文件: BonusRule.drl

                ==> 奖惩规则文件: AwardPunish.drl

                ==> 计算总工资规则: TotalRule.drl

【 3 】规则文件的组合(规则流):

 

                 ==> EduInfo.drl 含规则组 basic_salary

                 ==> ResumeRule.drl 含规则组 duty_salary

                 ==> BonusRule.drl 含规则组 bonus_salary

                 ==> AwardPunish.drl 含规则组 award_punish

                  ==> TotalRule.drl 含规则组 sum_salary

 

组合方式:

[start] --->  P[ basic_sal ary , duty_salary, bonus_salary, award_punish ]

                  ---> sum_salary ---> [end]

 

 

其中: P 表示并发, ---> 表示顺序 【规则流图在后面的实现中给出】

 

【 4 】编写测试文件: EmployTest.java

 

四、详细设计

 

【 1 】使用 Eclipse IDE 作为开发环境, drools5.1 作为规则引擎

【 2 】 为简单起见, Employ 类的属性作了简化处理,

              eduInfo , resume , annualExam,   awardPunish 均为 String ,

                   basic{duty,bonus, total}_salary , percent 作为 double 类型。

五、规则文件及规则流

 

               EduInfoRule.drl :

package myrules;


import sample.Employ;

 

rule "Bachelor"

       ruleflow-group "basic_salary"


when

   emp: Employ(eduInfo == "bachelor" );

then

   System.out.println( "exec rule Bachelor ... " );

   emp.setBasicSalary(1500);

end

 


rule "Master"

       ruleflow-group "basic_salary"


when

   emp: Employ(eduInfo== "master" )

then

   System.out.println( "exec rule Master ... " );

   emp.setBasicSalary(2500);

end

 


              Resume.drl

 


package myrules

import sample.Employ;

 


rule "Technician"

        ruleflow-group "duty_salary"


when

   emp: Employ(resume== "tech" )

then

   System.out.println( "exec rule Technician ... " );

   emp.setDutySalary(2000);

end

 


rule "Manager"

       ruleflow-group "duty_salary"


when

   emp: Employ(awardPunish== "manager" )

then

   System.out.println( "exec rule manager ... " );

   emp.setDutySalary(4500);

end

 


               BonusRule.drl

 


package myrules


import sample.Employ;

 

 

rule "Excellent"

       ruleflow-group "bonus_salary"


when

   emp: Employ(annualExam== "excellent" )

then

   System.out.println( "exec rule Excellent ... " );

   emp.setBonus(1000*1.0);

end

 


rule "Good"

        ruleflow-group "bonus_salary"

when

   emp: Employ(annualExam== "good" )

then

   System.out.println( "exec rule Good ... " );

   emp.setBonus(1000*0.9);

end

 


rule "Common"

       ruleflow-group "bonus_salary"


when

   emp: Employ(annualExam== "common" )

then

   System.out.println( "exec rule Common ... " );

   emp.setBonus(1000*0.6);

end

 


rule "failing"

        ruleflow-group "bonus_salary"


when

   emp: Employ(annualExam== "failing" )

then

   System.out.println( "exec rule failing ... " );

   emp.setBonus(1000*0.0);

end

 


               AwardPunish.drl

 


package myrules


import sample.Employ;

 


rule "Award"

        ruleflow-group "award_punish"


when

   emp: Employ(awardPunish== "award" )

then

   System.out.println( "exec rule Award ... " );

   emp.setPercent(1.10);

end

 


rule "Punishment"

        ruleflow-group "award_punish"

when

   emp: Employ(awardPunish== "punish" )

then

   System.out.println( "exec rule Punishment ... " );

   emp.setPercent(0.90);

end

 


rule "None"

       ruleflow-group "award_punish"


when

   emp: Employ(awardPunish== "none" )

then

   System.out.println( "exec rule None ... " );

   emp.setPercent(1.00);

end

 

 

 

               TotalRule.drl

 


package myrules

import sample.Employ;

 


rule "Total"

   ruleflow-group "sum_salary"


when

   emp: Employ()

then

   System.out.println( "exec rule Total ... " );

   double total = emp.getBasicSalary() +  emp.getDutySalary() +


                  emp.getBonus();                                  

   emp.setTotalSalary(total*emp.getPercent());

end

 

 

 

                创建规则流文件 simple.rf :

 

  

 

 

注意:

        [1] Split 结点类型为 OR ,约束选择 always true. 表示选择其规则组中所有符合事实的规则进行并发执行;

        [2] Join 结点类型为 AND ,表示当且进当上述规则组均执行完毕后,才执行后面的规则或进程。

 

 

 

 

六、测试代码:

 

Employ:

 

package sample;

 


public class Employ {

 

 

public static final double BONUS = 1000;


private String eduInfo ;

private String resume ;

private String annualExam ;

private String awardPunish ;


private double basicSalary ;

private double dutySalary ;

private double bonus ;

private double percent ;


private double totalSalary ;


// getter/setter methods


public String toString() {

return "[" + eduInfo + " " + resume + " " + annualExam +

" " + awardPunish + " " + basicSalary + " " + dutySalary +

" " + bonus + " " + totalSalary + "]" ;

}


}

 


EmployTest:

 


package sample;

 


import org.drools.KnowledgeBase;

import org.drools.KnowledgeBaseFactory;

import org.drools.builder.KnowledgeBuilder;

import org.drools.builder.KnowledgeBuilderError;

import org.drools.builder.KnowledgeBuilderErrors;

import org.drools.builder.KnowledgeBuilderFactory;

import org.drools.builder.ResourceType;

import org.drools.io.ResourceFactory;

import org.drools.logger.KnowledgeRuntimeLogger;

import org.drools.logger.KnowledgeRuntimeLoggerFactory;

import org.drools.runtime.StatefulKnowledgeSession;

 


public class EmployTest {


public static void main(String[] args) {


try {

// load up the knowledge base

KnowledgeBase kbase = readKnowledgeBase();

StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");

// go !

Employ emp = new Employ();

emp.setEduInfo("master");

emp.setResume("tech");

emp.setAnnualExam("good");

emp.setAwardPunish("award");

ksession.insert(emp);

ksession.startProcess("myrules.salary");

ksession.fireAllRules();

System.out.println("Basic Salary: " + emp.getBasicSalary());

System.out.println("Duty Salary: " + emp.getDutySalary());

System.out.println("Bonus : " + emp.getBonus());

System.out.println("rate : " + emp.getPercent());

System.out.printf("Total Salary: %.0f" , emp.getTotalSalary());

logger.close();

} catch (Throwable t) {

    t.printStackTrace();

}


}


private static KnowledgeBase readKnowledgeBase() throws Exception {

KnowledgeBuilder kbuilder =

KnowledgeBuilderFactory.newKnowledgeBuilder();

kbuilder.add(ResourceFactory.newClassPathResource("EduInfoRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("ResumeRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("BonusRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("AwardPunish.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("TotalRule.drl"), ResourceType.DRL);

kbuilder.add(ResourceFactory.newClassPathResource("salary.rf"), ResourceType.DRF);

KnowledgeBuilderErrors errors = kbuilder.getErrors();

if (errors.size() > 0) {

    for (KnowledgeBuilderError error: errors) {

        System.err.println(error);

    }

    throw new IllegalArgumentException("Could not parse knowledge.");

}

KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

return kbase;

}

 


}

 

              测试结果:

 

               exec rule Technician ...

            exec rule Master ...

exec rule Good ...

exec rule Award ...

exec rule Total ...

Basic Salary: 2500.0

Duty Salary: 2000.0

Bonus : 900.0

rate : 1.1

Total Salary: 5940

 

 

七、总结

 


Java drools 规则流基础:

 


【 1 】掌握规则引擎的基本工作原理;

【 2 】掌握规则文件的编写;

【 3 】掌握规则流图的绘制及应用程序集成。

【 4 】掌握规则组合的两种基本方式【并发和顺序】的实现方式。

 


下一步:

 


【 1 】更复杂的规则组合;

【 2 】规则文件的组织、管理;

【 3 】规则文件的自动生成;

【 4 】用户自定义规则;

你可能感兴趣的:(其他技术)