drools动态配置规则_SpringBoot入门建站全系列(三十四)使用Drools规则引擎做排班系统...

95ae2e2a1e79ed91a7307e50a6f19c1b.png

SpringBoot入门建站全系列(三十四)使用Drools规则引擎做排班系统

一、概述

Drools 是用 Java 语言编写的开放源码规则引擎,使用 Rete 算法对所编写的规则求值。Drools 允许使用声明方式表达业务逻辑。可以使用非 XML 的本地语言编写规则,从而便于学习和理解。并且,还可以将 Java 代码直接嵌入到规则文件中,这令 Drools 的学习更加吸引人。

总结一句,Drools就是使用已经写好的规则,对业务代码中提交给引擎保管的bean做筛选,筛选后的结果,就是我们想要的结果,例如排班系统,可以将人员存储到引擎中,然后按照排班规则(drl文件)对人员进行筛选归类。

Drools排班的简单示例,可以在Spring组件化构建的Drools组件中查看并下载。

首发地址:   品茗IT: https://www.pomit.cn/p/2486115243215361

如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。

下面我们来处理下面这种场景(该场景是从网上找来的,部分源码做了改动保证可运行):

场景:

  1. 员工分为两种:司机,外勤
  2. 每天分白、中、晚三个班次
  3. 每班 3 人,一个司机,两个外勤

规则: 1. 司机可以当外勤,外勤不可以当司机 2. 每个员工每个月至少休息 6 天 3. 每个员工连续上班不能超过 5 天 4. 工作分配应尽可能均匀

获取到人员排班信息。

二、基本配置

Drools的规则可以配置在XML和drl文件中,也可以从表里取,这里先讲下如何从表里取规则并应用。

2.1 Maven依赖

需要引入数据库相关配置和drools相关jar包,还要引入kie-api.

<dependency>
    

这样写,maven依赖不保证完全下载下来,有个jboss的jar包可能下载不下来,可以在pom.xml中多配置一个:

<repositories>
    

2.2 配置文件

在application.properties 中需要配置数据库相关信息的信息,如:

spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
spring.datasource.dbcp2.max-wait-millis=60000
spring.datasource.dbcp2.min-idle=20
spring.datasource.dbcp2.initial-size=2
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.connection-properties=characterEncoding=utf8
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.test-while-idle=true
spring.datasource.dbcp2.test-on-borrow=true
spring.datasource.dbcp2.test-on-return=false

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/cff?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=cff
spring.datasource.password=123456

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

spring.autoconfigure.exclude=org.activiti.spring.boot.SecurityAutoConfiguration

这只是数据库的配置而已,没有drools的配置。

三、 Drools规则引擎实体

按照前面说到的场景。

场景:

  1. 员工分为两种:司机,外勤
  2. 每天分白、中、晚三个班次
  3. 每班 3 人,一个司机,两个外勤

3.1 排期实体

因为要排班,首先要确定排班日历,实体如下。

WorkDate:

package 

3.2 排班对象实体

我们新建一个实体Worker。

Worker:

package 

3.3 班次实体

建立班次实体,保存排期及worker对象。

Shift:

package 

四、排班规则

这个规则可以存储到数据库中,也可以写到配置文件中,这里是写到数据库中,规则如下:

4.1 规则

package com.cff.springbootwork.drools

import com.cff.springbootwork.drools.domain.work.*;

rule "司机"
when
    shift : Shift(driver == null, $date : workDate, $no : no)
    worker : Worker(type == 1, easyDay >= 6, maxDay <= 4, $total : shiftTotal )
    eval( !shift.getWorkDate().containsWorker(worker) )
    not Worker(type == 1, shiftTotal < $total )
    not Shift(driver == null, workDate.day < $date.day)
    not Shift(driver == null, workDate.day == $date.day, no < $no )
then
    shift.setDriver( worker );
    worker.addShift( shift );
    update( shift );
    update( worker );
end

rule "外勤 1"
when
    shift : Shift(assistant1 == null, $date : workDate, $no : no)
    worker : Worker(easyDay >= 6, maxDay <= 4, $total : shiftTotal)
    eval( !shift.getWorkDate().containsWorker(worker) )
    not Worker( shiftTotal < $total )
    not Shift(assistant1 == null, workDate.day < $date.day)
    not Shift(assistant1 == null, workDate.day == $date.day, no < $no )
then
    shift.setAssistant1( worker );
    worker.addShift( shift );
    update( shift );
    update( worker );
end

rule "外勤 2"
when
    shift : Shift(assistant2 == null, $date : workDate, $no : no)
    worker : Worker(easyDay >= 6, maxDay <= 4, total : shiftTotal)
    eval( !shift.getWorkDate().containsWorker(worker) )
    not Worker( shiftTotal < total )
    not Shift(assistant2 == null, workDate.day < $date.day)
    not Shift(assistant2 == null, workDate.day == $date.day, no < $no )
then
    shift.setAssistant2( worker );
    worker.addShift( shift );
    update( shift );
    update( worker );
end

rule "移除班次"
when
    shift : Shift()
    eval( shift.isDone() )
then
    retract( shift );
end

这里:

  1. Worker(type == 1 表示worker是司机。easyDay >= 6, maxDay <= 4限定要筛选的worker休息日在6天以上,连续工作日在5天以下。
  2. not 关键字表示,非,就是表示满足not后面规则的实体需要被过滤掉。
  3. update关键字表示更新满足规则的实体。
  4. eval关键字表示过滤调返回值是false的实体。

4.2 规则入库

将规则存储到drools_rule文件中,建表语句如下:

CREATE TABLE `drools_rule` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL,
  `rule` text CHARACTER SET utf8mb4,
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `visible` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

4.3 规则CRUD

普通mybatis查询而已。

RulesDao:

package 

4.3 规则实体

普通实体,与数据库表字段对应而已,无特别意义。

package 

五、规则引擎的使用

这里,

  1. 先建立实体列表、日历和班次列表;
  2. 从数据库读规则并应用,返回KieSession;
  3. KieSession将所有实体插入并应用上面所述规则;
  4. 打印排班结果。

ShiftService:

package 

六、测试

建立测试web

ShiftController:

package 

七、其他实体

ShiftRes :

package 

ResultModel :

package 

SpringBoot入门建站全系列(三十四)使用Drools规则引擎做排班系统

一、概述

Drools 是用 Java 语言编写的开放源码规则引擎,使用 Rete 算法对所编写的规则求值。Drools 允许使用声明方式表达业务逻辑。可以使用非 XML 的本地语言编写规则,从而便于学习和理解。并且,还可以将 Java 代码直接嵌入到规则文件中,这令 Drools 的学习更加吸引人。

总结一句,Drools就是使用已经写好的规则,对业务代码中提交给引擎保管的bean做筛选,筛选后的结果,就是我们想要的结果,例如排班系统,可以将人员存储到引擎中,然后按照排班规则(drl文件)对人员进行筛选归类。

Drools排班的简单示例,可以在Spring组件化构建的Drools组件中查看并下载。

如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以 加入我们的java学习圈,点击即可加入 ,共同学习,节约学习时间,减少很多在学习中遇到的难题。

下面我们来处理下面这种场景(该场景是从网上找来的,部分源码做了改动保证可运行):

场景:

  1. 员工分为两种:司机,外勤
  2. 每天分白、中、晚三个班次
  3. 每班 3 人,一个司机,两个外勤

规则: 1. 司机可以当外勤,外勤不可以当司机 2. 每个员工每个月至少休息 6 天 3. 每个员工连续上班不能超过 5 天 4. 工作分配应尽可能均匀

获取到人员排班信息。

二、基本配置

Drools的规则可以配置在XML和drl文件中,也可以从表里取,这里先讲下如何从表里取规则并应用。

2.1 Maven依赖

需要引入数据库相关配置和drools相关jar包,还要引入kie-api.

<dependency>
    

这样写,maven依赖不保证完全下载下来,有个jboss的jar包可能下载不下来,可以在pom.xml中多配置一个:

<repositories>
    

2.2 配置文件

在application.properties 中需要配置数据库相关信息的信息,如:

spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
spring.datasource.dbcp2.max-wait-millis=60000
spring.datasource.dbcp2.min-idle=20
spring.datasource.dbcp2.initial-size=2
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.connection-properties=characterEncoding=utf8
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.test-while-idle=true
spring.datasource.dbcp2.test-on-borrow=true
spring.datasource.dbcp2.test-on-return=false

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/cff?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=cff
spring.datasource.password=123456

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

spring.autoconfigure.exclude=org.activiti.spring.boot.SecurityAutoConfiguration

这只是数据库的配置而已,没有drools的配置。

三、 Drools规则引擎实体

按照前面说到的场景。

场景:

  1. 员工分为两种:司机,外勤
  2. 每天分白、中、晚三个班次
  3. 每班 3 人,一个司机,两个外勤

3.1 排期实体

因为要排班,首先要确定排班日历,实体如下。

WorkDate:

package 

3.2 排班对象实体

我们新建一个实体Worker。

Worker:

package 

3.3 班次实体

建立班次实体,保存排期及worker对象。

Shift:

package 

四、排班规则

这个规则可以存储到数据库中,也可以写到配置文件中,这里是写到数据库中,规则如下:

4.1 规则

package com.cff.springbootwork.drools

import com.cff.springbootwork.drools.domain.work.*;

rule "司机"
when
    shift : Shift(driver == null, $date : workDate, $no : no)
    worker : Worker(type == 1, easyDay >= 6, maxDay <= 4, $total : shiftTotal )
    eval( !shift.getWorkDate().containsWorker(worker) )
    not Worker(type == 1, shiftTotal < $total )
    not Shift(driver == null, workDate.day < $date.day)
    not Shift(driver == null, workDate.day == $date.day, no < $no )
then
    shift.setDriver( worker );
    worker.addShift( shift );
    update( shift );
    update( worker );
end

rule "外勤 1"
when
    shift : Shift(assistant1 == null, $date : workDate, $no : no)
    worker : Worker(easyDay >= 6, maxDay <= 4, $total : shiftTotal)
    eval( !shift.getWorkDate().containsWorker(worker) )
    not Worker( shiftTotal < $total )
    not Shift(assistant1 == null, workDate.day < $date.day)
    not Shift(assistant1 == null, workDate.day == $date.day, no < $no )
then
    shift.setAssistant1( worker );
    worker.addShift( shift );
    update( shift );
    update( worker );
end

rule "外勤 2"
when
    shift : Shift(assistant2 == null, $date : workDate, $no : no)
    worker : Worker(easyDay >= 6, maxDay <= 4, total : shiftTotal)
    eval( !shift.getWorkDate().containsWorker(worker) )
    not Worker( shiftTotal < total )
    not Shift(assistant2 == null, workDate.day < $date.day)
    not Shift(assistant2 == null, workDate.day == $date.day, no < $no )
then
    shift.setAssistant2( worker );
    worker.addShift( shift );
    update( shift );
    update( worker );
end

rule "移除班次"
when
    shift : Shift()
    eval( shift.isDone() )
then
    retract( shift );
end

这里:

  1. Worker(type == 1 表示worker是司机。easyDay >= 6, maxDay <= 4限定要筛选的worker休息日在6天以上,连续工作日在5天以下。
  2. not 关键字表示,非,就是表示满足not后面规则的实体需要被过滤掉。
  3. update关键字表示更新满足规则的实体。
  4. eval关键字表示过滤调返回值是false的实体。

4.2 规则入库

将规则存储到drools_rule文件中,建表语句如下:

CREATE TABLE `drools_rule` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET utf8mb4 DEFAULT NULL,
  `rule` text CHARACTER SET utf8mb4,
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `visible` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

4.3 规则CRUD

普通mybatis查询而已。

RulesDao:

package 

4.3 规则实体

普通实体,与数据库表字段对应而已,无特别意义。

package 

五、规则引擎的使用

这里,

  1. 先建立实体列表、日历和班次列表;
  2. 从数据库读规则并应用,返回KieSession;
  3. KieSession将所有实体插入并应用上面所述规则;
  4. 打印排班结果。

ShiftService:

package 

六、测试

建立测试web

ShiftController:

package 

七、其他实体

ShiftRes :

ResultModel :

详细实体及完整代码,可以访问《SpringBoot入门建站全系列(三十四)使用Drools规则引擎做排班系统》查看完整文章

品茗IT-博客专题:https://www.pomit.cn/lecture.html汇总了Spring专题、Springboot专题、SpringCloud专题、web基础配置专题。

快速构建项目

Spring项目快速开发工具:

一键快速构建Spring项目工具

一键快速构建SpringBoot项目工具

一键快速构建SpringCloud项目工具

一站式Springboot项目生成

Mysql一键生成Mybatis注解Mapper

Spring组件化构建

SpringBoot组件化构建

SpringCloud服务化构建

喜欢这篇文章么,喜欢就加入我们一起讨论Java Web吧!

34a2f58a405b8a8ea4d149801d4521f2.png
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
全自动排班使用说明 1、在设置好年份与表头。 "2、每年1月1日,在中按一个排班周期设置好人员名单,将自动生成全年排班表,   第一行就是1月1日上班人员,如使用该表时不是1月1日,可以通过调整中   的排班次序来获得之后日期的正确排班表。单元格内的多行人员代表当天几个班   (如三行就是早中晚),当天增加一个班,就在人员单元格内按[Alt-Enter]换行。" 3、在表中,请自行增加本年的节日,假日会以红底黑字增亮显示 4、在中设置好班次与工时。 5、在中可以自动统计每人每月或全年的工作量 "6、对于不规则情况的排班,如换班,可以在当月人员名单中手动更改,另外,如果每天   的班次大于三个,会出现单元格显示不下的情况,这时可以用快捷键来修改字体大小。" "7、快捷键:   Ctrl-q 所有表保护状态,只有人员显示栏可以更改   Ctrl-e 取消所有表的保护状态,所有栏都可编辑   Ctrl-r 所有表人员名称字体加大   Ctrl-t 所有表人员名称字体减小 Ctrl-p 下打印排班表 Alt-F4 退出EXECL" "8、注意事项:理论上没有限制,但由于单元格显示宽高度有限(字体太小影响显示效果),       本表建议适用一个班最多三人,一天最多四个班上班(四行)的情况,不符合       该条件的可以使用排班表(考勤版)》解决。"

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值