快速集成和使用 solon-flow 规则与流引擎(用 yaml 编写业务规则)
本文参考自:https://www.cnblogs.com/studyjobs/p/18125096
规则引擎技术的主要思想是将应用程序中的业务规则分离出来,业务规则不再以程序代码的形式驻留在系统中,而是存储在独立的文件或者数据库中,完全独立于程序。业务人员可以像管理数据一样对业务规则进行管理。业务规则在程序运行时被加载到规则引擎中供应用系统调用。
solon-flow 是新的规则引擎技术,由 OpenSolon 开源组织提供的基于 Java 语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以 yaml 规则脚本的形式存放在文件或特定的存储介质中(例如数据库),使得业务规则的变更不需要修改项目代码、不需要重启服务器就可以立即生效。
本篇博客的 demo 以个税计算器为例,介绍如何使用 solon-flow 规则引擎,有关具体技术细节,限于篇幅有限,这里不会介绍,具体细节可以参考官网。
solon-flow 官网地址:https://solon.noear.org/article/learn-solon-flow
solon-flow 源码下载地址:https://gitee.com/opensolon/solon/tree/main/solon-projects/solon-flow/solon-flow
1、搭建工程
搭建一个 solon 工程,结构如下:

solon-flow 规则引擎将规则编写在以 .yml (很流行的配置文)为后缀的文件中,yml 文件默认也是使用 yaml + java 语言编写,所以学习起来很容易。
一般情况下,我们使用 IDEA 编写业务规则,默认情况下 .yml 文件会被打包到项目 jar 包中,为了方便后续调整规则,我们可以将 yml 文件的内容,存储到数据库中或者 oss 云盘中,程序在运行时从 jar 包外部读取规则内容。
完束上的 pom 文件的内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.noear</groupId>
<artifactId>solon-parent</artifactId>
<version>3.0.8</version>
<relativePath />
</parent>
<groupId>com.example</groupId>
<artifactId>demo-rule</artifactId>
<version>1.0</version>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-web</artifactId>
</dependency>
<!-- 规则与流引擎 -->
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-flow</artifactId>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-logging-simple</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.noear</groupId>
<artifactId>solon-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、代码细节展示
此文的 demo 是个税计算器,我们创建一个用于向规则引擎传递数据的实体类
package com.example.demo.model;
import lombok.Data;
@Data
public class Calculation {
//税前工资
private double wage;
//应纳税所得额
private double wagemore;
//税率
private double cess;
//速算扣除数
private double preminus;
//扣税额
private double wageminus;
//税后工资
private double actualwage;
}
这里不考虑缴纳社保和专项扣除等因素,个税计算的规则如下:

之后我们在 flow/rule.yml 中编写的规则如下:
id: rule
nodes:
- id: "tax_setWagemore" #计算应纳税所得额
when: |
import java.time.LocalDate;
//2022-10-1 后生效
return cal.getWage() > 0 && LocalDate.now().compareTo(LocalDate.of(2022,10,1)) > 0;
task: |
double wagemore = cal.getWage() - 5000;
cal.setWagemore(wagemore);
- id: "tax_3000" #设置税率、速算扣除数
when: "cal.getWagemore() <= 3000"
task: |
cal.setCess(0.03);//税率
cal.setPreminus(0);//速算扣除数
- id: "tax_12000"
when: "cal.getWagemore() > 3000 && cal.getWagemore() <= 12000"
task: |
cal.setCess(0.1);//税率
cal.setPreminus(210);//速算扣除数
- id: "tax_25000"
when: "cal.getWagemore() > 12000 && cal.getWagemore() <= 25000"
task: |
cal.setCess(0.2);
cal.setPreminus(1410);
- id: "tax_35000"
when: "cal.getWagemore() > 25000 && cal.getWagemore() <= 35000"
task: |
cal.setCess(0.25);
cal.setPreminus(2660);
- id: "tax_55000"
when: "cal.getWagemore() > 35000 && cal.getWagemore() <= 55000"
task: |
cal.setCess(0.25);
cal.setPreminus(2660);
- id: "tax_80000"
when: "cal.getWagemore() > 55000 && cal.getWagemore() <= 80000"
task: |
cal.setCess(0.35);
cal.setPreminus(7160);
- id: "tax_max"
when: "cal.getWagemore() > 80000"
task: |
cal.setCess(0.45);
cal.setPreminus(15160);
- id: "tax_result"
when: "cal.getWage() > 0 && cal.getWagemore() > 0 && cal.getCess() > 0"
task: |
//扣税额
double wageminus = cal.getWagemore() * cal.getCess() - cal.getPreminus();
double actualwage = cal.getWage() - wageminus;
cal.setWageminus(wageminus);
cal.setActualwage(actualwage);
System.out.println("--税前工资:"+cal.getWage());
System.out.println("--应纳税所得额:"+cal.getWagemore());
System.out.println("--税率:" + cal.getCess());
System.out.println("--速算扣除数:" + cal.getPreminus());
System.out.println("--扣税额:" + cal.getWageminus());
System.out.println("--税后工资:" + cal.getActualwage());
本 demo 设定每次被调用时,都去读取 rule.yml 的内容(可时实生效),具体代码在 RuleService 中实现:
package com.example.demo.dso;
import com.example.demo.model.Calculation;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.flow.ChainContext;
import org.noear.solon.flow.FlowEngine;
@Component
public class RuleService {
//调用Drools规则引擎实现个人所得税计算
public Calculation calculate(Calculation calculation) throws Throwable {
FlowEngine flowEngine = FlowEngine.newInstance();
flowEngine.load(Chain.parseByUri("file:src/main/resources/flow/rule.yml")); //动态加载源码下的文件,修改后实时生效
//构建上下文
ChainContext ctx = new ChainContext();
ctx.put("cal", calculation);
//执行规则
flowEngine.eval("rule", ctx);
//返回运行算后的
return calculation;
}
}
然后在 RuleController 中对外提供计算个税的接口,只需要传递一个税前工资额即可计算得出结果
@Mapping("rule")
@Controller
public class RuleController {
@Inject
RuleService ruleService;
@Mapping("calculate")
public Calculation calculate(double wage) throws Throwable {
Calculation calculation = new Calculation();
calculation.setWage(wage);
calculation = ruleService.calculate(calculation);
System.out.println(calculation);
return calculation;
}
}
3、验证成果
启动后,可以访问接口 http://localhost:8080/rule/calculate?wage=10000 即可查看到静态页面,输入 10000 元计算个税,如下图:

结果可以发现,税率是 0.1,执行的是 rule.yml 文件中的名称为 tax_12000 的规则,此时你可以使用 IDEA 修改一下,比如将税率修改为 0.2
- id: "tax_12000"
when: "cal.getWagemore() > 3000 && cal.getWagemore() <= 12000"
task: |
cal.setCess(0.2);//这里故意将税率修改为 0.2
cal.setPreminus(210);//速算扣除数
注意不需要重启 IDEA 的项目(可时实生效),此时重新点击页面中的计算,发现刚刚修改的规则生效了,如下图所示:

好了,以上就是有关 solon 使用 drools 规则引擎的介绍(在 spring 里差不多),有兴趣的话可以下载源代码进行验证。
本示例,源码下载地址:
https://gitee.com/opensolon/solon-flow_rule-demo
快速集成和使用 solon-flow 规则与流引擎(用 yaml 编写业务规则)的更多相关文章
- 第2-4-2章 规则引擎Drools入门案例-业务规则管理系统-组件化-中台
目录 3. Drools入门案例 3.1 业务场景说明 3.2 开发实现 3.3 小结 3.3.1 规则引擎构成 3.3.2 相关概念说明 3.3.3 规则引擎执行过程 3.3.4 KIE介绍 3. ...
- 第2-4-3章 规则引擎Drools基础语法-业务规则管理系统-组件化-中台
目录 4. Drools基础语法 4.1 规则文件构成 4.2 规则体语法结构 4.3 注释 4.4 Pattern模式匹配 4.5 比较操作符 4.5.1 语法 4.5.2 操作步骤 4.6 执行指 ...
- 第2-4-5章 规则引擎Drools高级语法-业务规则管理系统-组件化-中台
目录 6. Drools高级语法 6.1 global全局变量 6.2 query查询 6.3 function函数 6.4 LHS加强 6.4.1 复合值限制in/not in 6.4.2 条件元素 ...
- 第2-4-1章 规则引擎Drools介绍-业务规则管理系统-组件化-中台
目录 规则引擎 Drools 1. 问题引出 2. 规则引擎概述 2.1 什么是规则引擎 2.2 使用规则引擎的优势 2.3 规则引擎应用场景 2.4 Drools介绍 规则引擎 Drools 全套代 ...
- 快速集成iOS基于RTMP的视频推流
前言 这篇blog是iOS视频直播初窥:<喵播APP>的一个补充. 因为之前传到github上的项目中没有集成视频的推流.有很多朋友简信和微博上问我推流这部分怎么实现的. 所以, 我重新集 ...
- 快速集成图片浏览器快速集成图片浏览器->MJPhotoBrowser的使用
介绍: 一个比较完整的图片浏览器,高仿了新浪微博的图片浏览效果,功能包括:下载浏览互联网图片,点击缩略图全屏显示图片.当加载较大图片时会出现圆形进度条,滑动浏览所有图片.保存图片到本地相册.GIF图片 ...
- iOS简单快速集成Cordova
如果你对于什么是Cordova还不了解,可以先移步到我另一个文章:Cordoval在iOS中的运用整理 里面有详细的介绍跟如何搭建Cordova:而本文则是要介绍JiaCordova插件,如果你有一点 ...
- Spring Boot 揭秘与实战(三) 日志框架篇 - 如何快速集成日志系统
文章目录 1. 默认的日志框架 logback2. 常用的日志框架 log4j 1.1. 日志级别 1.2. 日志文件 3. 源代码 Java 有很多日志系统,例如,Java Util Logging ...
- Android Studio快速集成讯飞SDK实现文字朗读功能
今天,我们来学习一下怎么在Android Studio快速集成讯飞SDK实现文字朗读功能,先看一下效果图: 第一步 :了解TTS语音服务 TTS的全称为Text To Speech,即“从文本到语音” ...
- ShareSDK入门指南:Android 10分钟快速集成
ShareSDK 官方已提供Android 快速集成教程,以官方教程为参考,本文重点指导大家在集成中遇到的问题. Android 快速集成官方教程:http://wiki.mob.com/Androi ...
随机推荐
- 无需配对数据的对比学习图像到图像转换,助力跨域物体检测 | BMVC'24
来源:晓飞的算法工程笔记 公众号,转载请注明出处 论文: Improving Object Detection via Local-global Contrastive Learning 论文地址:h ...
- 表里不一--限制容器内存4G,free还是32G
前言 最近有个新同事问了我一个问题,明明通过limit给容器内存限制了4G,为什么进容器看到的还是宿主机的内存32G docker run -it --rm -m 512m ubuntu:18.04 ...
- Node.js Express 框架(2)
1.读取文件并返回给客户端 res.sendFile(path):读取文件并返回给客户端,适合静态页面 app.get("/",function(req,res){ res.sen ...
- Trino 436 - 使用教程(亲测,详细)
第一章 Trino简介 1. Trino概述 Trino是一个分布式SQL查询引擎,旨在查询分布在一个或多个异构数据源上的大型数据集.如果使用的是数TB或数PB的数据,那么很可能使用的是与Hadoop ...
- 基于 .NET 的 Nuget 发版工具
背景 由于 Natasha 及周边项目发版任务多,文件结构也不简单,之前一直使用基于 Github 管道脚本和 XUnit 来发版.这个方案对于发版环境与条件依赖性较强,且不够灵活,因此萌生出做一个本 ...
- Dapr-6: Dapr 状态管理构建块
第 6 章 Dapr 状态管理构建块 The Dapr state management building block | Microsoft Docs 分布式应用程序由一组独立的服务构成.尽管每个服 ...
- 中电金信:零售经营“新赛道” ——基于手机银行APP专区调研的客群精细化运营分析报告
随着银行业竞争的不断深入及新客户增量日渐"到顶",各家银行的客群竞争逐渐由"跑马圈地"进入"精耕细作"的新阶段,在客群精准化服务方面不断深 ...
- 技术实践|数据迁移中GBK转UTF8字符集问题分析
导语:在国产化创新的大背景下,数据库迁移项目逐渐增多,在数据库迁移过程中,源数据库和目标数据库字符集有时会不同,这时如何进行字符集转换则成为了一个重要的问题,同时在转换过程中还需要确保数据的完整性和一 ...
- 出现io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1的原因及解决办法
错误信息 在使用Netty构建Server服务器的时候,之前用得好好的,最近整理了一下就出现了以下错误: WARN (AbstractChannelHandlerContext.java:294)- ...
- Java保留两位小数的几种写法总结
转载 本文列举了几个方法: 1. 使用java.math.BigDecimal 2. 使用java.text.DecimalFormat 3. 使用java.text.NumberFormat 4. ...