Spring Boot中實現規則引擎原始碼教程

banq發表於2024-06-03

在軟體開發中,我們經常需要應用一組規則或條件來過濾和處理資料。使用傳統的 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(<font>"/user")
public class UserController {
    
    @GetMapping
    public List<User> getAllUser(){
        return userData();
    }

    private List<User> userData() {
        List<User> 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(<font>"sum"));

    private final Predicate<User> predicate;

    Rule(Predicate<User> predicate) {
        this.predicate = predicate;
    }

    public Predicate<User> getPredicate() {
        return predicate;
    }
}

讓我建立一個 TestRule 介面來定義不需要實現的方法。

import java.util.function.Predicate;

public interface TestRule {
    <T> Predicate<T> 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<T> {
    private List<TestRule> rules;

    public RuleEngine() {
        this.rules = new ArrayList<>();
    }

    public void addRule(TestRule rule) {
        rules.add(rule);
    }

    public List<T> filter(List<T> items) {
        List<T> 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(<font>"/user")
public class UserController {
    
    @GetMapping
    public List<User> getAllUser(){
        RuleEngine<User> ruleEngine = new RuleEngine<>();
        ruleEngine.addRule(Rule.AGE_GREATER_THAN_30);
        ruleEngine.addRule(Rule.NAME_STARTS_WITH_SUM);
        List<User> filteredUser = ruleEngine.filter(userData());
        return filteredUser;
    }

    private List<User> userData() {
        List<User> 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

相關文章