转自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 】用户自定义规则;