当前位置: 首页 > 后端技术 > Java

学习使用规则引擎Drools让你早点下班

时间:2023-04-02 09:21:31 Java

前言现在有这样一个需求,网购,需要根据不同的规则计算产品折扣,比如VIP客户增加5折,购买金额超过1000元增加10%的折扣等,并且这些规则可能随时更改,甚至增加新的规则。面对这个需求,你是如何实现的?难道当计算规则改变时,业务代码必须修改,重新测试,并上线。其实我们可以通过规则引擎来实现。Drools是一个开源的业务规则引擎,可以很容易地与springboot应用程序集成。在本文中,我们将使用Drools来实现上述需求。引入依赖我们创建一个springboot应用,在pom中加入drools相关的依赖,如下:org.droolsdrools-core7??.59.0。最终版org.droolsdrools-compiler7??.59.0.Finalorg.droolsdrools-decisiontables7??.59.0.FinalDrools配置类创建名为DroolsConfig的配置java类。@ConfigurationpublicclassDroolsConfig{//规则文件的路径privatestaticfinalStringRULES_CUSTOMER_RULES_DRL="rules/customer-discount.drl";私人静态最终KieServiceskieServices=KieServices.Factory.get();@BeanpublicKieContainerkieContainer(){KieFileSystemkieFileSystem=kieServices.newKieFileSystem();kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));KieBuilderkb=kieServices.newKieBuilder(kieFileSystem);kb.buildAll();KieModulekieModule=kb.getKieModule();KieServicekieContainer.newKieContainer(kieModule.getReleaseId());返回kieContainer;}}定义了一个KieContainer的SpringBean,KieContainer通过加载应用/resources文件夹下的规则文件来构建规则引擎。创建一个KieFileSystem实例并配置规则引擎并从应用程序的资源目录加载规则的DRL文件。使用KieBuilder实例构建drools模块。我们可以使用KieServive单例实例来创建KieBuilder实例。最后,使用KieService创建一个KieContainer并将其配置为springbean。添加业务模型以创建订单对象OrderRequest,并将此类中的字段作为输入信息发送回定义的drools规则,以计算给定客户订单的折扣金额。@Getter@SetterpublicclassOrderRequest{/***客户编号*/privateStringcustomerNumber;/***年龄*/privateIntegerage;/***订单金额*/privateIntegeramount;/***客户类型*/privateCustomerTypecustomerType;}另外,定义一个客户类型CustomerType的枚举,规则引擎会根据这个值计算客户订单折扣百分比,如下图。publicenumCustomerType{忠诚,新,不满意;publicStringgetValue(){返回this.toString();最后,创建一个订单折扣类OrderDiscount来表示计算出的最终折扣,如下所示。@Getter@SetterpublicclassOrderDiscount{/***discount*/privateIntegerdiscount=0;我们将使用上述响应对象返回计算出的折扣。在定义drools规则之前,先在DroolsConfig类中定义drools规则的目录。现在我们在/src/main/resources/rules目录下添加customer-discount.drl文件,并在里面定义相应的规则。虽然这个drl文件不是java文件,但是还是很容易理解的。我们使用一个名为orderDiscount的全局参数,它可以在多个规则之间共享。一个drl文件可以包含一个或多个规则。我们可以使用mvel语法来指定规则。此外,每个规则都使用rule关键字进行描述。每个规则都有一个when-then语法来定义规则的条件。根据订单请求的输入值,我们正在为结果添加折扣。如果规则表达式匹配,每个规则都会向全局结果变量添加额外的折扣。完整的规则源码如下:importcom.alvin.drools.model.OrderRequest;importcom.alvin.drools.model.CustomerType;globalcom.alvin.drools.model.OrderDiscountorderDiscount;dialect"mvel"//Rule1:根据Age判断规则“Agebaseddiscount”when//当客户小于20岁或大于50岁OrderRequest(age<20||age>50)then//添加10%的折扣System.out.println("==========儿童/长者加10%优惠==============");orderDiscount.setDiscount(orderDiscount.getDiscount()+10);end//规则2:基于客户类型的规则rule"Customertypebaseddiscount-Loyalcustomer"when//当客户类型为LOYALOrderRequest(customerType.getValue=="LOYAL")然后//添加5%的折扣System.out.println("==========为忠诚客户增加5%的折扣==============");orderDiscount.setDiscount(orderDiscount.getDiscount()+5);endrule"Customertypebaseddiscount-others"whenOrderRequest(customerType.getValue!="LOYAL")thenSystem.out.println("==========为新客户或不满意的客户增加3%的折扣==============");orderDiscount.setDiscount(orderDiscount.getDiscount()+3);endrule"Amountbaseddiscount"whenOrderRequest(amount>1000L)thenSystem.out.println("==========添加5%的折扣超过1000==============”);orderDiscount.setDiscount(orderDiscount.getDiscount()+5);endAddService层创建一个名为OrderDiscountService的服务类,如下:@ServicepublicclassOrderDiscountService{@AutowiredprivateKieContainerkieContainer;publicOrderDiscountgetDiscount(OrderRequestorderRequest){OrderDiscountorderDiscount=newOrderDiscount();//打开会话KieSessionkieSession=kieContainer.newKieSession();//设置折扣对象setkieGlobal("orderDiscount",orderDiscount);//设置订单对象kieSession.insert(orderRequest);//触发规则kieSession.fireAllRules();//终止会话kieSession.dispose();退货订单折扣;}}注入KieContainer实例并创建一个KieSession实例。设置了一个OrderDiscount类型的全局参数,用于保存规则执行结果。使用insert()方法将请求对象传递到drl文件。调用fireAllRules()方法来触发所有规则。最后,通过调用KieSession的dispose()方法终止会话。添加Controller创建一个名为OrderDiscountController的Controller类,具体代码如下:@RestControllerpublicclassOrderDiscountController{@AutowiredprivateOrderDiscountServiceorderDiscountService;@PostMapping("/get-discount")publicResponseEntitygetDiscount(@RequestBodyOrderRequestorderRequest){OrderDiscount折扣=orderDiscountService.getDiscount(orderRequest);返回新的ResponseEntity<>(折扣,HttpStatus.OK);}}测试运行springboot应用程序并通过发送客户订单请求JSON访问RESTAPI端点。对于年龄<20且金额>1000的LOYAL客户类型,我们应该根据我们定义的规则获得20%的折扣。综上所述,我们通过drools规则引擎简单的实现了这样一个打折业务。现在产品经理说要加一条规则,比如地址是杭州加10折,就直接改drl文件,其他时间钓鱼用。嗯,哈哈~~。你可以去官网探索更多关于drools的用法。