Hello everyone, I am Bucai Chen~
Alipay sent a red envelope, copy: 817180432 Go to Alipay to search and get it, ranging from 1 yuan to 20 yuan per person
Now there is such a demand, online shopping needs to calculate product discounts according to different rules, such as 5% discount for VIP customers, 10% discount for purchases exceeding 1,000 yuan, etc., and these rules may change at any time, or even increase new rules. Faced with this demand, how do you realize it? Could it be that when the calculation rules change, the business code must be modified, retested, and launched.
In fact, we can implement it through a rule engine. Drools is an open source business rule engine that can be easily integrated with spring boot applications. In this article, we will use Drools to realize the above-mentioned requirements.
Regarding the rule engine, there are two previous articles that introduced it, as follows:
-
In-depth comparison of rule engines, LiteFlow vs Drools!
-
Talk about the small and beautiful rule engine LiteFlow
Other rule engines will be introduced later……
Introducing dependencies
We create a spring boot application and add drools-related dependencies to the pom, as follows:
<dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>7.59.0.Final</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.59.0.Final</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-decisiontables</artifactId> <version>7.59.0.Final</version> </dependency>
Drools configuration class
Create a configuration java class called DroolsConfig
.
@Configuration public class DroolsConfig { // specify the path to the rule file private static final String RULES_CUSTOMER_RULES_DRL = "rules/customer-discount.drl"; private static final KieServices kieServices = KieServices.Factory.get(); @Bean public KieContainer kieContainer() { KieFileSystem kieFileSystem = kieServices. newKieFileSystem(); kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL)); KieBuilder kb = kieServices. newKieBuilder(kieFileSystem); kb.buildAll(); KieModule kieModule = kb. getKieModule(); KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId()); return kieContainer; } }
-
A
Spring Bean
ofKieContainer
is defined, andKieContainer
is used to load the application under the/resources
folder rule files to build the rules engine. -
Creates a
KieFileSystem
instance and configures the rule engine and loads the rule’sDRL
file from the application’s resource directory. -
Use
KieBuilder
instance to builddrools
module. We can use KieServive singleton instance to createKieBuilder
instance. -
Finally, use
KieService
to create aKieContainer
and configure it as aspring bean
.
Add business model
Create an order object OrderRequest
. The fields in this class are then sent as input information to the defined drools
rules to calculate the discount amount for a given customer order.
@Getter @Setter public class OrderRequest { /** * client number */ private String customerNumber; /** * age */ private Integer age; /** * order amount */ private Integer amount; /** * Customer type */ private CustomerType customerType; }
In addition, define an enumeration of customer type CustomerType
from which the rules engine will calculate the customer order discount percentage, as shown below.
public enum CustomerType { LOYAL, NEW, DISSATISFIED; public String getValue() { return this.toString(); } }
Finally, create an order discount class OrderDiscount
to represent the calculated final discount, as shown below.
@Getter @Setter public class OrderDiscount { /** * Discount */ private Integer discount = 0; }
We will return the calculated discount using the above response object.
Define drools rules
The previous DroolsConfig
class specifies the drools
rule directory, now we add customer in the
file, which defines the corresponding rules./src/main/resources/rules
directory -discount.drl
Although this drl
file is not a java file, it is still easy to understand.
-
We use a global parameter called
orderDiscount
that can be shared between multiple rules. Pay attention to Gongzhong account: code ape technology column, reply keywords: 1111 Get Ali’s internal java performance tuning manual! -
A
drl
file can contain one or more rules. We can use themvel
syntax to specify rules. Additionally, each rule is described using therule
keyword. -
Each rule uses
when-then
syntax to define the conditions of the rule. -
Based on the input value of the order request, we are adding a discount to the result. Each rule adds an additional discount to the global result variable if the rule expression matches.
The complete rule source code is as follows:
import com.alvin.drools.model.OrderRequest; import com.alvin.drools.model.CustomerType; global com.alvin.drools.model.OrderDiscount orderDiscount; dialect "mvel" // Rule 1: Judging by age rule "Age based discount" when // When the customer's age is under 20 or over 50 OrderRequest(age < 20 || age > 50) then // add 10% discount System.out.println("===========Adding 10% discount for Kids/ senior customer==============="); orderDiscount.setDiscount(orderDiscount.getDiscount() + 10); end // Rule 2: Rules based on customer type rule "Customer type based discount - Loyal customer" when // When the customer type is LOYAL OrderRequest(customerType. getValue == "LOYAL") then // add 5% discount System.out.println("==========Adding 5% discount for LOYAL customer==============="); orderDiscount.setDiscount(orderDiscount.getDiscount() + 5); end rule "Customer type based discount - others" when OrderRequest(customerType. getValue != "LOYAL") then System.out.println("===========Adding 3% discount for NEW or DISSATISFIED customer==============="); orderDiscount.setDiscount(orderDiscount.getDiscount() + 3); end rule "Amount based discount" when OrderRequest(amount > 1000L) then System.out.println("===========Adding 5% discount for amount more than 1000$==============="); orderDiscount.setDiscount(orderDiscount.getDiscount() + 5); end
Add Service layer
Create a service class called OrderDiscountService
, as follows:.
@Service public class OrderDiscountService { @Autowired private KieContainer kieContainer; public OrderDiscount getDiscount(OrderRequest orderRequest) { OrderDiscount orderDiscount = new OrderDiscount(); // start the session KieSession kieSession = kieContainer. newKieSession(); // set discount object kieSession.setGlobal("orderDiscount", orderDiscount); // set the order object kieSession.insert(orderRequest); // trigger rule kieSession.fireAllRules(); // abort the session kieSession.dispose(); return order Discount; } }
-
Inject a
KieContainer
instance and create aKieSession
instance. -
A global parameter of type
OrderDiscount
is set, which will save the rule execution result. -
Use the
insert()
method to pass the request object to thedrl
file. -
Call the
fireAllRules()
method to fire all rules. -
Finally, terminate the session by calling the
dispose()
method ofKieSession
.
Add Controller
Create a Controller
class named OrderDiscountController
, the specific code is as follows:
@RestController public class OrderDiscountController { @Autowired private OrderDiscountService orderDiscountService; @PostMapping("/get-discount") public ResponseEntity<OrderDiscount> getDiscount(@RequestBody OrderRequest orderRequest) { OrderDiscount discount = orderDiscountService. getDiscount(orderRequest); return new ResponseEntity<>(discount, HttpStatus.OK); } }
Test it
Run the spring boot
application and access the REST API endpoint by sending the customer order request JSON.
-
For
LOYAL
customer type with age < 20 and amount > 1000, we should get discount of20%
according to the rules we defined.
Summary
We have simply implemented such a discount business through the drools
rule engine. Now the product manager asks you to add a rule, for example, if the address is Hangzhou plus 10% discount, you can directly change the drl file. Others Just spend time fishing, haha~~. You can go to the official website to explore more about the usage of drools
.
One last sentence (don’t prostitute, please pay attention)
Every article by Chen is carefully output. If this article is helpful or inspiring to you, please like, watch, repost, and bookmark. Your support is the biggest motivation for me to persevere!
In addition, Chen’s Knowledge Planet has been opened, and the official account replies to the key words: Knowledge Planet is limited to 20 yuan coupons to join, only 109 yuan, a meal, but the value of the planet’s feedback is huge, At present, the Spring family bucket actual combat series, the billion-level data sub-database sub-table actual combat, the DDD micro-service actual combat column, I want to enter the big factory, Spring, Mybatis and other framework source code, the architecture actual combat 22 lectures, etc.. Each additional column The price will increase by 20 yuan
Pay attention to the official account: [Code Ape Technology Column], there are awesome fan benefits in the official account, reply: join the group, you can join the technical discussion group, discuss technology with everyone, and brag!