1.引入依赖
<!--规则引擎-->
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>6.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>6.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>6.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>6.5.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>6.5.0.Final</version>
</dependency>
2.实现
public Order handleRules(String id, Order order) {
//获取规则开始
String rules = "";
Rules ru = ruleRespository.findById(id).get();
if (ru != null && ru.getRules() != null) {
rules = ru.getRules();
}
//获取规则结束
Order result = null;
KieSession kieSession = null;
KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
try{
//转换DRL文件形式
kb.add(ResourceFactory.newByteArrayResource(rules.getBytes("utf-8")),ResourceType.DRL);
// 检查规则正确性
if(kb.hasErrors()){
log.error(kb.getErrors().toString());
}
KnowledgeBase knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase();
knowledgeBase.addKnowledgePackages(kb.getKnowledgePackages());
kieSession = knowledgeBase.newKieSession();
log.info("订单使用规则传入的订单信息={}",order);
kieSession.insert(order);//fact插入
kieSession.fireAllRules();
for (Object per : kieSession.getObjects(new ClassObjectFilter(Order.class))) {
result = ((Order) per);
}
}catch (Exception e){
log.info("执行规则出现异常");
}finally {
if(null!=kieSession){
kieSession.dispose();//释放
}
}
return result;
}
3.规则(使用的是数据库获取,数据库表的设计可以按照这样设计)
INSERT INTO obk_rules VALUES
('3',
'import com.sutpc.maas.orderbook.domain.Order;
import com.sutpc.maas.orderbook.domain.StaffType;import com.sutpc.maas.orderbook.domain.OrderType;
import com.sutpc.maas.orderbook.domain.ConnectionType;
import com.sutpc.maas.orderbook.domain.Price;
import com.sutpc.maas.orderbook.domain.DiscountType;
function Boolean containStr(String routeNo,String routeNos){
Boolean isContain = routeNos.contains(routeNo);
return isContain;
}
function Price queryPrice(Double routePrice){
Price price = new Price();
price.setPrice(routePrice);
price.setActualPrice(routePrice);
price.setDiscountType(DiscountType.NON);
return price;
}
rule "rule1"
no-loop true
when
$order:Order(StaffType.INTERNAL==passenger.getType()&&orderType==OrderType.IMMED&&containStr(route.routeNo,"K4"))
then
System.out.print("进入rule1");
Price price = new Price();
price.setPrice($order.getRoute().getRoutePrice());
price.setActualPrice(2.4);
price.setDiscountType(DiscountType.FIX);
$order.setPrice(price);
update($order);
end
rule "rule2"
no-loop true
when
$order:Order(StaffType.EXTERNAL==passenger.getType()&&orderType==OrderType.IMMED&&containStr(route.routeNo,"K4"))
then
System.out.print("进入rule2");
Price price = queryPrice($order.getRoute().getRoutePrice());
$order.setPrice(price);
update($order);
end
rule "rule3"
no-loop true
when
$order:Order(StaffType.EXTERNAL==passenger.getType()&&orderType==OrderType.IMMED&&containStr(route.routeNo,"K1,K2"))
then
System.out.print("进入rule3");
Price price = queryPrice($order.getRoute().getRoutePrice());
$order.setPrice(price);
update($order);
end
rule "rule4"
no-loop true
when
$order:Order(StaffType.INTERNAL==passenger.getType()&&orderType==OrderType.IMMED&&containStr(route.routeNo,"K1,K2"))
then
System.out.print("进入rule4");
Price price = new Price();
price.setPrice($order.getRoute().getRoutePrice());
price.setActualPrice(0.0);
price.setDiscountType(DiscountType.FIX);
$order.setPrice(price);
update($order);
end',
'订单策略规则',
'Y'
);
4.test
@Test
public void handleOrderRule(){
Order order = Order.builder()
.orderType(OrderType.IMMED)
.passenger(Passenger.builder().type(StaffType.INTERNAL).build())
.route(Route.builder().routeNo("K4").routePrice(6.0).build())
.build();
Order handledOrder = ruleService.handleRules("3", order);
Assert.assertEquals(new Double(2.4),handledOrder.getPrice().getActualPrice());
}
解释:这个方法是使用了数据库动态获取的,避免加载文件;可以先写好规则文件,然后再存储到数据库中,我存储使用的字段类型是text(测试内存数据库中可以使用clob类型)。