试用JBoss Rules

来源:互联网 发布:高分起名软件 编辑:程序博客网 时间:2024/04/27 20:28
这两天研究了一下JBoss Rules,最大的感觉是JBoss Rules的文档写得不错,而且Eclipse IDE插件的功能也挺不错,相比JBoss JBPM好多了。

    个人觉得规则引擎就是把一堆if/else逻辑从业务代码转移到配置文件中,这样如果业务规则发生变化就不用更改代码,而且如果描述这种规则的语言足够清晰明白,更改业务规则的任务就可以由业务人员来完成了,Domain Specific Language就是来干这事的。

    JBoss Rules的内部机制,这里就不再详细介绍了,已经有先行者对JBoss Rules的参考手册进行了整理,参见www.blogjava.net/guangnian0412/category/11762.html。

    我针对一个实际的业务场景写了一个例子,应用场景是这样的,一个汽车网的销售人员的提成有一定的规则,大致的规则根据售出价格的折扣来决定提成比例,比如如果10000元的广告服务,最后售出价格是4500,销售人员的提成是0.3%。

    创建工程
 
    假定已经安装了Eclipse JBoss Rules插件,新建一个Rules工程。

    创建规则文件

    创建一个规则文件如下:ruby 代码

 

1. #描述如何计算销售人员提成比例的规则
2. package org.gaofubing.commision
3.
4. import org.gaofubing.discount.CommisionComputer;
5.
6.
7. #折扣小于5折
8. rule "lessThanFive" 9.
10. when
11. computer:CommisionComputer(discount < 5)
12. then
13. computer.setDeduct(0.03);
14. end
15.
16. #折扣等于5折
17. rule "equalsFive" 18.
19. when
20. computer:CommisionComputer(discount == 5)
21. then
22. computer.setDeduct(0.1);
23. end
24.
25. #折扣大于5折小于等于6折
26. rule "betweenFiveAndSix" 27.
28. when
29. computer: CommisionComputer(discount:discount,discount > 5,discount <= 6)
30. then
31. computer.setDeduct(((discount.doubleValue() -5) * 0.5 + 6 * 0.1 ) / discount.doubleValue());
32. end
33.
34. #折扣大于6折小于等于7折
35. rule "betweenSixAndSeven" 36.
37. when
38. computer: CommisionComputer(discount:discount,discount > 6,discount <= 7)
39. then
40. computer.setDeduct(((discount.doubleValue() -6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) / discount.doubleValue());
41. end
42.
43. #折扣大于7折小于等于8折
44. rule "betweenSevenAndEight" 45.
46. when
47. computer:CommisionComputer(discount:discount,discount > 7,discount <= 8)
48. then
49. computer.setDeduct(((discount.doubleValue() -7) * 0.65 + (7-6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) / discount.doubleValue());
50. end
51.
52. #折扣大于8折小于等于9折
53. rule "betweenEightAndNine" 54.
55. when
56. computer:CommisionComputer(discount:discount,discount > 8,discount <= 9)
57. then
58. computer.setDeduct(((discount.doubleValue() -8) * 0.7 + (8-7) * 0.65 + (7-6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) / discount.doubleValue());
59. end
60.
61. #折扣大于9折
62. rule "greaterThanNine" 63.
64. when
65. computer:CommisionComputer(discount:discount,discount > 9)
66. then
67. computer.setDeduct(((discount.doubleValue() -9) * 0.85 + (9-8) * 0.7 + (8-7) * 0.65 + (7-6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) / discount.doubleValue());
68. end
 
    在测试的时候发生过一些问题,如果要描述折扣大于8小于9的条件,使用如下代码就不行
   
    java 代码

 

computer: CommisionComputer(discount:discount,discount > 6) && CommisionComputer(discount <= 7)
 
    另外CommisionComputer的discount属性是double类型,Rules的then部分会将其自动封箱,但是不会自动拆箱,所以如果then部分使用discount就会报错,必须使用discount.doubleValue();
 创建Java类

    CommisionComputer类的主要方法是computeCommision方法接受一个合同价格和售出价格,返回销售人员的提成数额。java 代码

 

1. package org.gaofubing.discount;
2.
3. import java.io.InputStreamReader;
4. import java.io.Reader;
5.
6. import org.apache.commons.logging.Log;
7. import org.apache.commons.logging.LogFactory;
8. import org.drools.RuleBase;
9. import org.drools.RuleBaseFactory;
10. import org.drools.WorkingMemory;
11. import org.drools.compiler.PackageBuilder;
12. import org.drools.rule.Package;
13.
14. public class CommisionComputer
15. {
16. private static final String RULE_FILE = "discount.drl";
17.
18. protected static Log log = LogFactory.getLog(CommisionComputer.class);
19.
20. //折扣 21. private double discount;
22.
23. //提成比例 24. private double deduct;
25.
26. /**
27. * 根据合同价格和销售价格计算销售人员提成
28. * @param contractPrice 合同价格
29. * @param saledPrice 销售价格
30. * @return 提成
31.
*/ 32. public double computeCommision(double contractPrice,double saledPrice)
33. {
34. try {
35. //读取规则集,创建工作内存区 36. RuleBase ruleBase = readRule(RULE_FILE);
37. WorkingMemory workingMemory = ruleBase.newWorkingMemory();
38.
39. log.debug("执行规则前的提成比例值为:" + getDeduct());
40.
41. //激活规则 42. setDiscount(saledPrice * 10d /contractPrice);
43. workingMemory.assertObject(this);
44. workingMemory.fireAllRules();
45.
46. log.debug("执行规则后的提成比例值为:" + getDeduct());
47.
48. } catch (Throwable t) {
49. t.printStackTrace();
50. log.debug("不能成功执行规则",t);
51. }
52. return contractPrice * getDeduct();
53. }
54.
55. /**
56. * 读取规则文件
57. * @param ruleFile 规则文件名称,相对于类路径
58.
*/ 59. private RuleBase readRule(String ruleFile) throws Exception
60. {
61. //读取规则文件 62. Reader source = new InputStreamReader(CommisionComputer.class.getClassLoader().getResourceAsStream(ruleFile));
63.
64. //创建包 65. PackageBuilder builder = new PackageBuilder();
66. builder.addPackageFromDrl( source );
67. Package pkg = builder.getPackage();
68.
69. //构建规则集 70. RuleBase ruleBase = RuleBaseFactory.newRuleBase();
71. ruleBase.addPackage( pkg );
72. return ruleBase;
73. }
74.
75. public double getDiscount()
76. {
77. return discount;
78. }
79.
80. public void setDiscount( double discount)
81. {
82. this.discount = discount;
83. }
84.
85. public double getDeduct()
86. {
87. return deduct;
88. }
89.
90. public void setDeduct( double deduct)
91. {
92. this.deduct = deduct;
93. }
94.
95. }
 
    创建测试

    测试代码如下:java 代码

 

1. public void testDiscountLessThanFive()
2. {
3. double commision = computer.computeCommision(10000,4500);
4. assertEquals(commision,10000*0.03);
5. }
6.
7. public void testDiscountEqualsFive()
8. {
9. double commision = computer.computeCommision(10000,5000);
10. assertEquals(commision,10000*0.1);
11. }
12.
13. public void testDiscountBetweenFiveAndSix()
14. {
15. double commision = computer.computeCommision(10000,5500);
16. double discount = 5500 * 10d /10000;
17. double deduct = ((discount -5) * 0.5 + 6 * 0.1 ) /discount;
18. assertEquals(commision,10000*deduct);
19. }
20.
21. public void testDiscountBetweenSixAndSeven()
22. {
23. double commision = computer.computeCommision(10000,6500);
24. double discount = 6500 * 10d /10000;
25. double deduct = ((discount -6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) /discount;
26. assertEquals(commision,10000*deduct);
27. }
28.
29. public void testDiscountBetweenSevenAndEight()
30. {
31. double commision = computer.computeCommision(10000,7500);
32. double discount = 7500 * 10d /10000;
33. double deduct = ((discount -7) * 0.65 + (7-6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) /discount;
34. assertEquals(commision,10000*deduct);
35. }
36.
37. public void testDiscountBetweenEightAndNine()
38. {
39. double commision = computer.computeCommision(10000,8500);
40. double discount = 8500 * 10d /10000;
41. double deduct = ((discount -8) * 0.7 + (8-7) * 0.65 + (7-6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) /discount;
42. assertEquals(commision,10000*deduct);
43. }
44.
45. public void testDiscountGreaterThanNine()
46. {
47. double commision = computer.computeCommision(10000,9500);
48. double discount = 9500 * 10d /10000;
49. double deduct = ((discount -9) * 0.85 + (9-8) * 0.7 + (8-7) * 0.65 + (7-6) * 0.6 + (6 - 5) * 0.5 + 5 * 0.1 ) /discount;
50. assertEquals(commision,10000*deduct);
51. }
原创粉丝点击