Java 两条规则中有一条不开火
我是JAVA和Drools的初学者,所以不要问我为什么要这么做:D任务是实现一个简单的系统,可以计算两种商品(不同颜色)的关税和价格。我用getter和setter创建了一个简单的类:Java 两条规则中有一条不开火,java,drools,priority-queue,rule-engine,Java,Drools,Priority Queue,Rule Engine,我是JAVA和Drools的初学者,所以不要问我为什么要这么做:D任务是实现一个简单的系统,可以计算两种商品(不同颜色)的关税和价格。我用getter和setter创建了一个简单的类: package com.sample; public class Pen { private String color; private int quantity; private double tariff; private double subTotal; pub
package com.sample;
public class Pen {
private String color;
private int quantity;
private double tariff;
private double subTotal;
public String getColor(){
return color;
}
public void setColor(String color){
this.color=color;
}
public int getQuantity(){
return quantity;
}
public void setQuantity(int quantity){
this.quantity=quantity;
}
public double getTariff(){
return tariff;
}
public void setTariff(double tariff){
this.tariff=tariff;
}
public double getSubTotal(){
return subTotal;
}
public void setSubTotal(double subTotal){
this.subTotal=subTotal;
}
}
任务是从一个CSV文件中读取一些预定义的数据,并将其写入另一个CSV(尚未实现写入)。处理输入并调用会话的类如下所示:
public class CSVReader {
public void CSVToJava() {
String CSVFile = "csvExample.csv";
BufferedReader buffer = null;
String line = "";
String delimiter = ",";
List<Pen> penList = new ArrayList<Pen>();
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
buffer = new BufferedReader(new FileReader(CSVFile));
while ((line = buffer.readLine()) != null) {
String[] pens = line.split(delimiter);
Pen redPen = new Pen();
Pen bluePen = new Pen();
if (pens[0].equalsIgnoreCase("Blue Pen")) {
bluePen.setColor(pens[0]);
bluePen.setQuantity(Integer.parseInt(pens[1].trim()));
penList.add(bluePen);
ksession.insert(bluePen);
} else {
redPen.setColor(pens[0]);
redPen.setQuantity(Integer.parseInt(pens[1].trim()));
penList.add(redPen);
ksession.insert(redPen);
}
}
ksession.fireAllRules();
printPenList(penList);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Throwable t) {
t.printStackTrace();
} finally {
if (buffer != null) {
try {
buffer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void printPenList(List<Pen> penListToPrint) {
for (int i = 0; i < penListToPrint.size(); i++) {
System.out.println(penListToPrint.get(i).getColor() + "," + penListToPrint.get(i).getQuantity() + ","
+ penListToPrint.get(i).getTariff() + "," + penListToPrint.get(i).getSubTotal());
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("com/Drools/BluePen.drl"), ResourceType.DRL);
kbuilder.add(ResourceFactory.newClassPathResource("com/Drools/RedPen.drl"), ResourceType.DRL);
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;
}
}
一切都是这样
我的主要问题是打印输出看起来像这样-->
每行应包含4个字段,前两个字段在while循环中的CSVReader类中计算,而最后两个字段(在本例中为3.5和21.0或红色笔)使用Drools计算。正如你所看到的,蓝笔的规则根本没有生效,我无法解决这个问题。。。如果有人能帮忙,我会非常感激:)
编辑:解决这个问题后,我用另外3条规则编辑了代码,这3条规则分布在2个DRL文件中:
package com.drools //First.drl
import com.sample.Pen;
rule "Subtotal for blue pen" salience 2
when
item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"))
then
item.setTotal(item.getTotal() + item.getSubTotal());
end
rule "Subtotal for red pen" salience 2
when
item : Pen(item.getColor().equalsIgnoreCase("RED PEN"))
then
item.setTotal(item.getTotal() + item.getSubTotal());
end
package com.drools //Second.drl
import com.sample.Pen;
rule "Discounted total price" salience 1
when
item : Pen((item.getTotal()) > 100.0)
then
item.setTotal(0.85 * item.getTotal());
end
我也在会话中添加了文件类路径,以便于启动。调用fireAll方法时,第二次drl激发没有规则激发,总数量乘以0.85(total
是在Pen
类中声明的静态变量,因此我可以从每种颜色收集添加的suTotal
s),即使显著性最低-->应最后触发,正确的数量应为140*0.85=119
看起来像这样:
Red Pen,30,3.0,90.0
Blue Pen,20,2.5,50.0
140
也许有人也能明白这一点,到目前为止,你们的建议都很好:)我不是专家,但我建议在第一条规则之后切换红笔和蓝笔,看看它是否不会触发规则。或者可能是CSV文件读取的问题。规则条件中的字符串比较不应使用Java equals方法。Drools正在使用它自己的。(但请注意-5.x语法比参考文档中所示的要严格一些,并且在5.2/3/…[laune]的小版本之间也有所不同。) 看看示例4.4(我更正了示例中缺少的
“
):
您应该为您的规则尝试此语法(还要注意,您的数量是整数而不是浮点):
作为补充说明,规则的操作部分中的(double)
强制转换不是必需的。在Java中,将double和整数相乘会得到一个double值,该值已经是关税和小计成员的类型。两个文件都有规则
rule "less or equal to 10"
rule "more than 10"
您不能这样做。规则由名称标识;与另一个规则同名的规则将以静默方式覆盖第一个规则。未定义来自不同DRL文件的加载顺序
在Drools 5.x期间,这是否以及如何工作进行了长时间的讨论,但现在这是桥下的水,您必须坚持下去。(我不确定Drools 6.x是否允许这样做。请查阅文档。)
感谢@Wis确认Drools 6.x在编译中存在名称相同的规则时会引发编译错误,而不管这些规则是在同一DRL文件中还是在不同的文件中。您仍然可以使用equals.和equalsIgnoreCase(如OP所述)是另一种方法。你是对的,equals确实有效。如果我没有弄错的话,在条件中只能使用Java的一小部分。我记得不能使用一些
Calendar
方法。但是有一点不同,drools==运算符是空安全的。我冒昧地补充了一句关于它们之间语法的警告6.x和5.x版本。原始问题没有指明drools borgmater使用的是哪个版本。然后在点击链接时要小心。你的编辑是相关的。这应该是一个评论,而不是答案。我同意,但我不允许用我目前的观点评论。做了一个测试以确保drools 6.x:它不允许d重复名称。它的结尾为:java.lang.IllegalStateException:[4,0]:重复规则名称:小于或等于10[12,0]:重复的规则名称:超过10个。
。我将编辑您的帖子以确保完整性。@在编辑之前,请确保相同或不同文件中的规则没有差异。发生了另一个问题,也是由于触发了规则,我已编辑了包含详细信息的帖子。似乎salience工作不正常,或者我缺少了一些内容g:-/您缺少基本的东西。首先,阅读有关修改和更新的内容。其次,使用静态(类)变量是一种制造恶作剧的好方法。你有两个钢笔对象——总数通过两者都可见,因此对于总数为140的笔,规则会对红色的笔触发一次,然后对蓝色的笔触发一次,结果是140*0.85*0.85。第三,避免突出,除非你绝对确定你离不开它。@laune我测试过,可以确认非法状态在两种情况下都会出现重复规则名称的例外情况:在一个文件和两个不同的文件中有两个名称相同的规则(假设两个DRL文件在同一个编译中)。
package com.drools //First.drl
import com.sample.Pen;
rule "Subtotal for blue pen" salience 2
when
item : Pen(item.getColor().equalsIgnoreCase("BLUE PEN"))
then
item.setTotal(item.getTotal() + item.getSubTotal());
end
rule "Subtotal for red pen" salience 2
when
item : Pen(item.getColor().equalsIgnoreCase("RED PEN"))
then
item.setTotal(item.getTotal() + item.getSubTotal());
end
package com.drools //Second.drl
import com.sample.Pen;
rule "Discounted total price" salience 1
when
item : Pen((item.getTotal()) > 100.0)
then
item.setTotal(0.85 * item.getTotal());
end
Red Pen,30,3.0,90.0
Blue Pen,20,2.5,50.0
140
1: rule simple_rule
2: when
3: Student( name == "Andy" )
4: then
5: end
when
item : Pen(color == "BLUE PEN", quantity > 10)
rule "less or equal to 10"
rule "more than 10"