在软件开发中,我们经常需要应用一组规则或条件来过滤和处理数据。使用传统的 if 和 else 条件管理这些规则可能会变得繁琐且难以维护。规则引擎提供了一种更灵活、更有条理的方法来定义和执行这些规则。在本文中,我们将探讨如何使用 Java 函数式编程原理在 Spring Boot 项目中构建一个简单的规则引擎。
什么是规则引擎?
规则引擎是一个专家系统程序,它对输入数据运行规则,如果任何条件匹配,则执行相应的操作。
规则引擎负责管理一组规则,并将它们应用于一组对象。它根据定义的规则过滤对象并返回过滤结果。
案例
在这个应用程序中,首先我将创建一个UserController.java类并创建一个返回用户列表的Rest端点。
import com.example.spring_boot_rule_engine_demo.model.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping
public List
getAllUser(){
return userData();
}
private List
userData() {
List
users =
new ArrayList<>();
User user1 =
new User("sumit", 33);
User user2 =
new User("agam", 13);
User user3 =
new User("mohit", 23);
User user4 =
new User("kailash", 43);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
return users;
}
}
现在,我们要求只获取年龄大于 30 岁、姓名以 sum 开头的用户。
因此,现在我们需要创建两条规则,并在向客户端返回响应前应用这两条规则。
定义规则:
首先,我们将使用一个名为 Rule 的枚举来定义规则。枚举中的每条规则都代表我们要评估的特定条件或标准。
import com.example.spring_boot_rule_engine_demo.model.User;
import java.util.function.Predicate;
public enum Rule implements TestRule {
AGE_GREATER_THAN_30(user -> user.getAge() > 30),
NAME_STARTS_WITH_SUM(user -> user.getName().startsWith("sum"));
private final Predicate predicate;
Rule(Predicate
predicate) {
this.predicate = predicate;
}
public Predicate
getPredicate() {
return predicate;
}
}
让我创建一个 TestRule 接口来定义不需要实现的方法。
import java.util.function.Predicate;
public interface TestRule {
Predicate
getPredicate();
}
创建自己的规则引擎:
接下来,我们创建 RuleEngine 类。该类将处理规则的管理和执行。它维护一个规则列表,并提供添加新规则和根据这些规则过滤对象的方法。
实现过滤逻辑
在 RuleEngine 类的过滤方法中,我们遍历对象列表,并使用 Java 8 Stream API 中的 allMatch 方法应用每条规则。该方法会检查给定对象是否通过了所有规则。如果所有规则都通过,我们就会将该对象添加到过滤列表中。
import com.example.spring_boot_rule_engine_demo.rule.TestRule;
import java.util.ArrayList;
import java.util.List;
public class RuleEngine
{
private List
rules;
public RuleEngine() {
this.rules = new ArrayList<>();
}
public void addRule(TestRule rule) {
rules.add(rule);
}
public List
filter(List
items) {
List
filteredItems =
new ArrayList<>();
for (T item : items) {
if (rules.stream().allMatch(rule -> rule.getPredicate().test(item))) {
filteredItems.add(item);
}
}
return filteredItems;
}
}
public
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
在 UserController.java 类中创建的获取所有用户 API 中,我们演示了规则引擎的用法。我们创建了一个用户对象列表,并用两条规则初始化了规则引擎:AGE_GREATER_THAN_30 和 NAME_STARTS_WITH_SUM。然后,我们调用规则引擎的过滤器方法,并传递用户对象列表。规则引擎会对每个用户应用规则,并返回过滤后的列表。
最后,我们遍历过滤后的列表,返回符合指定规则的用户列表。
import com.example.spring_boot_rule_engine_demo.engine.RuleEngine;
import com.example.spring_boot_rule_engine_demo.model.User;
import com.example.spring_boot_rule_engine_demo.rule.Rule;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping
public List
getAllUser(){
RuleEngine
ruleEngine =
new RuleEngine<>();
ruleEngine.addRule(Rule.AGE_GREATER_THAN_30);
ruleEngine.addRule(Rule.NAME_STARTS_WITH_SUM);
List
filteredUser = ruleEngine.filter(userData());
return filteredUser;
}
private List
userData() {
List
users =
new ArrayList<>();
User user1 =
new User("sumit", 33);
User user2 =
new User("agam", 13);
User user3 =
new User("mohit", 23);
User user4 =
new User("kailash", 43);
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
return users;
}
}
源码:Github