Mastering LiteFlow: Build Decoupled, Hot‑Reloadable Business Rules in Spring Boot
This article introduces LiteFlow, a powerful rule‑engine framework for Spring Boot, explains its advantages, shows how to define rules in XML/JSON/YML, and provides a complete end‑to‑end example with code snippets and hot‑swap components for flexible business logic.
Environment: SpringBoot 2.7.16
1. Introduction
LiteFlow is a modern rule‑engine framework that combines orchestration and rule‑engine features. Complex business logic often leads to tightly coupled, hard‑to‑maintain code; LiteFlow decouples logic, enabling low‑coupling, flexible systems that can be hot‑reloaded without code changes.
LiteFlow Advantages
By using LiteFlow you can transform waterfall‑style code into a component‑centric structure where components are decoupled and driven by rules. Its DSL is the simplest among open‑source rule engines, allowing you to get started in ten minutes.
Components can be hot‑replaced in real time, and new components can be added to an existing flow to change business logic instantly.
LiteFlow’s script components support many scripting languages and integrate fully with Java, allowing any logic to be implemented in scripts.
Rules and scripts can be stored in databases or registries, and the framework provides extensible interfaces for customization.
Rule File Formats
LiteFlow supports XML, JSON, and YML rule definitions. Example XML:
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="example_01">
THEN(a, b, c)
</chain>
</flow>Rule operators:
THEN : serial execution (a → b → c)
WHEN : parallel execution
<chain name="chain1">
WHEN(a, b, c);
</chain>SWITCH : conditional branching
<chain name="chain1">
SWITCH(a).to(b, c, d);
</chain>IF : conditional execution
<chain name="chain1">
THEN(
IF(x, a),
b
);
</chain>Binary IF executes x → a → b when x is true, otherwise x → b.
<chain name="chain1">
THEN(
IF(x, a, b),
c
);
</chain>More rule types are available on the official site.
2. Practical Example
Environment Configuration
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>2.11.4.2</version>
</dependency> # liteflow configuration
liteflow:
rule-source: flows/*.el.xmlRule Flow Definition
The complete rule flow looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="processOrder">
THEN(
initOrder,
IF(amount, discountOrder),
SWITCH(userType).to(vipDiscountOrder, normalDiscountOrder),
completeOrder
)
</chain>
</flow>Components referenced (e.g., initOrder, amount) are Spring beans.
Component Implementations
@Component("initOrder")
public class InitOrderComponent extends NodeComponent {
@Override
public void process() {
System.out.println("初始化订单...");
Order order = this.getContextBean(Order.class);
double sum = order.getItems().stream()
.mapToDouble(item -> item.getPrice()
.multiply(BigDecimal.valueOf(item.getQuantity()))
.doubleValue())
.sum();
order.setTotalAmount(BigDecimal.valueOf(sum));
}
} @Component("amount")
public class AmountComponent extends NodeIfComponent {
@Override
public boolean processIf() throws Exception {
System.out.println("判断总金额,超过100元打折");
Order order = this.getContextBean(Order.class);
return order.getTotalAmount().doubleValue() >= 100D;
}
} @Component("userType")
public class UserTypeComponent extends NodeSwitchComponent {
@Override
public String processSwitch() throws Exception {
User user = this.getContextBean(User.class);
if (user.isVip()) {
return "vipDiscountOrder";
}
return "normalDiscountOrder";
}
} @Component("vipDiscountOrder")
public class VIPDiscountOrderComponent extends NodeComponent {
@Override
public void process() {
System.out.println("VIP会员打9折");
Order order = this.getContextBean(Order.class);
order.setTotalAmount(order.getTotalAmount()
.multiply(BigDecimal.valueOf(9))
.divide(BigDecimal.valueOf(10), RoundingMode.HALF_UP));
}
} @Component("normalDiscountOrder")
public class NormalDiscountOrderComponent extends NodeComponent {
@Override
public void process() {
System.out.println("普通会员不打折");
}
} @Component("completeOrder")
public class CompleteOrderComponent extends NodeComponent {
@Override
public void process() throws Exception {
System.out.println("订单折扣执行完成,最后收尾...");
}
}Test Execution
// Directly inject FlowExecutor to start the rule flow
@Resource
private FlowExecutor flowExecutor;
@Test
public void testExample02() {
Order order = new Order();
order.setId(1L);
order.setSno("S001");
List<OrderItem> items = new ArrayList<>();
items.add(new OrderItem(1L, 2, BigDecimal.valueOf(22)));
items.add(new OrderItem(2L, 1, BigDecimal.valueOf(24.5)));
items.add(new OrderItem(3L, 5, BigDecimal.valueOf(66.3)));
order.setItems(items);
User user = new User();
user.setId(1L);
user.setVip(false);
LiteflowResponse response = flowExecutor.execute2Resp("processOrder", null, order, user);
if (!response.isSuccess()) {
Exception e = response.getCause();
e.printStackTrace();
} else {
System.out.println("流程成功执行...");
System.out.println("最终应付款:" + response.getContextBean(Order.class).getTotalAmount().doubleValue());
}
}The console prints detailed execution information.
After changing the user type, the flow adapts accordingly.
This concludes the article; hope it helps you build flexible, low‑coupling business logic with LiteFlow.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
