微服务组件-规则引擎

时间:2024-03-19 09:09:04

BRMS

微服务组件-规则引擎

版本记录

版本号

版本描述

编写人

修订日期

V1.0.0

草稿

 

2016-06-23

V1.0.1

增加自动生成**、变更**功能,取消容器-应用权限配置功能

 

2016-07-05

 

 

 

 

设计说明

基于drools 6.4.0.Final 版本

 

 

目    录

版本记录... 1

设计说明... 1

目    录... 2

APP-规则引擎... 4

左侧菜单... 4

BRM市场... 4

说明... 4

Docker服务器... 5

说明... 5

UI 5

Docker实例... 5

说明... 5

UI 5

配置管理... 6

说明... 6

UI原型... 6

功能... 6

相关表定义... 6

规则库管理... 7

说明... 7

UI原型... 7

功能... 7

相关表定义... 7

KIE-SERVER管理... 8

说明... 8

UI原型... 8

功能... 8

相关表定义... 9

外部接口... 9

取kie服务器状态... 9

KIE容器-**... 9

说明... 9

UI原型... 10

容器-**管理... 10

功能... 10

相关表定义... 11

外部接口... 11

取kie服务器所有容器... 11

API-规则引擎... 12

调用模式一:返回值调用... 12

调用容器... 12

描述... 12

定义... 12

参数... 12

方法响应... 13

调用模式二:触发器调用(待续)... 14

调用容器... 14

规则开发流程... 14

积分等级应用... 14

1.信用卡积分规则开发流程... 14

1.1规则需求描述... 14

定义规则:... 15

1.2 创建项目... 15

1.3 规则库数据对象... 15

1.4 规则库定义规则... 16

1.5 测试场景... 18

1.6 规则部署... 19

1.7 规则调运... 21

智能决策辅助应用... 22

1. 停车场收费计算-决策表开发流程... 22

1.1规则需求描述... 22

1.2规则库定义规则... 22

1.2.1定义实体... 22

1.2.2规则文件-决策表创建... 29

1.3 规则部署... 34

1.3.1构建项目... 34

1.3.2创建容器... 34

1.4 规则调运... 36

风险控制应用... 39

流程引擎(BPM)应用... 39

附录... 39

规则文件结构... 39

规则文件示例... 40

DefineObject对象(自定义对象) 41

 

 

 

APP-规则引擎

左侧菜单

 

 

BRM市场

说明

规则库、和规则容器服务器 资源市场采购

 

 

Docker服务器

说明

用于部署Docker容器

UI

 

Docker实例

说明

用于部署KIE-SERVER 服务、部署kie-drools 规则库

UI

 

配置管理

说明

可对规则引擎的公共参数进行在线管理

UI原型

 

功能

增加、删除(批量)、修改、查找

相关表定义

 

规则库管理

说明

管理不同公司(企业)规则库和规则服务器之间的对应关系,方便后续的自动化管理

UI原型

 

规则库管理

 

功能

管理规则库和规则服务器之间的关系

访问规则库

相关表定义

 

 

 

KIE-SERVER管理

说明

可配置多个的kie-server信息,包括名称,服务url,用户名、密码等,并通过接口判断kie-server是否可用。

UI原型

 

功能

增加、删除(批量)、修改、查找

拓展功能

1.       新增KIE-SERVER服务所需的Docker容器环境

2.       部署kie-server远程服务器,修改配置参数

3.       启动kie-server服务 、检查启动日志

 

相关表定义

 

 

外部接口

取kie服务器状态

 

KIE容器-**

说明

通过接口动态取所有容器,配置规则容器的相关**。

展示列表逻辑

1.       通过接口取所有容器

2.       通过数据库取所有已存储容器

3.       合并展示

4.       操作生成**、变更**时保存进数据库

UI原型

容器-**管理

 

其中容器名称和服务器名称对应下图

 

功能

生成**、变更**

相关表定义

 

外部接口

 

取kie服务器所有容器

 

 

API-规则引擎

调用模式一:返回值调用

 

调用容器

描述

根据**、服务器名、容器名、会话状态(默认1为无状态)、执行参数调用

定义

方法路径

/rule/1.0.0/container/exec

请求类型

post

返回类型

json

返回编码

Utf-8

方法名称

exec

业务逻辑

 

 

参数

jsonParam

参数类型

string

参数来源

requestbody

参数说明

{ secretKey:”必填-**,如:9873485209shdiufw937”

,serverName:”必填-服务器名”

,containerName:” 必填-容器名”

,sessionType:默认1(1:有状态 2:无状态)

,globalMap:{“公共对象”}

,defineArray:[{“自定义对象”}]

,otherArray:[{“其它对象”}]}

 

Ø  注:

defineArray单个对象的格式必须拥有以下属性:

/**规则文件包名*/

   private String packageName;

   /**对象名*/

   private String objectName;

   /**实例数据*/

   private Map<String,Object> instanceData;

详见附录DefineObject

方法响应

返回类型

json

字段说明

{_CODE:返回编码,_MSG:"提示信息",_DATA:{}}

示例数据

{"_MSG":"Container test4 successfully called.","_CODE":1,"_DATA":{"GET_OBJECTS":[{"id":"1","name":"8888中文","result":"8888"},["999999"]]}}

 

 

调用模式二:触发器调用(待续)

 

调用容器

 

规则开发流程

积分等级应用

1.信用卡积分规则开发流程

1.1规则需求描述

现在有一个应用场景:网站伴随业务产生而进行的积分发放操作。

比如支付宝信用卡还款奖励积分等。

 

发放积分可能伴随不同的运营策略和季节性调整,发放数目和规则完全不同,如果使用硬编码的方式去伴随业务调整而修改,代码的修改、管理、优化、测试、上线将是一件非常麻烦的事情,所以,将发放规则部分提取出来,交给Drools做统一管理,可以极大程度的解决这个问题。

 

我们定义一下积分发放规则:

 

积分的发放参考因素有:

交易笔数、交易金额数目、信用卡还款次数、生日特别优惠等

 

定义规则:

 

a) 增加积分规则

1. 过生日,则加10分,并且将当月交易比数翻倍后再计算积分

 

2. 2016-06-01 - 2016-12-31每月信用卡还款3次以上,每满3笔赠送30分

 

3. 当月购物总金额100以上,每100元赠送10分

 

4. 当月购物次数5次以上,每五次赠送50分

 

5. 特别的,如果全部满足了要求,则额外奖励100分

 

b) 减少积分规则

1. 发生退货,扣减10分

 

2. 退货金额大于等于100,扣减100分

 

根据这些规则,我们让Drools为我们计算出为任一用户需要发放的积分数为多少。

1.2 创建项目

 

1.3 规则库数据对象

 

 

 

 

 

1.4 规则库定义规则

 

a) 加分规则(addpoint.drl)

 

b) 减分规则(subpoint.drl)

 

规则应进行检验

 

 

 

1.5 测试场景

 

 

 

 

 

 

 

1.6 规则部署

项目要在构建&部署成功后才会打jar包。

 

 

 

 

 

 

 

 

 

 

 

 

 

1.7 规则调运

使用工具类(KieServicesRestUtil)进行远程容器调用

 

 

返回结果:

{"_MSG":"Container JF successfully called.","_CODE":1,"_DATA":{"GET_OBJECTS":[{"backMondy":100,"backNums":1,"billThisMonth":6,"birthDay":true,"buyMoney":1000,"buyNums":10,"point":50280,"userName":"ko"}]}}

 

 

 

智能决策辅助应用

1. 停车场收费计算-决策表开发流程

1.1规则需求描述

停车场都有其明确的收费标准,但不同地区地段都有不同的规定,这种规定的可变性比较多,如果要快速实现自动计算停车收费功能,那么使用规则是一个很好的选择。而一般的停车场计费都会使用类似于表格的计费公示办法,这与决策表的表达方法是基本相同的。某地区的停车场白天临时停车计费指导价如下:

计收单位为:元/15分钟。

 

1.2规则库定义规则

1.2.1定义实体

该实体的定义有两种:一种是通过规则库的web界面操作,另一种是自己定义然后导出为jar包上传到规则库里。

通过规则库的web界面操作:

 

然后你可以有两种操作方式:方式一点击“添加字段”按钮:

 

 

方式二点击“添加字段”按钮:

 

在该界面中和eclipse工具界面一样自定义属性和方法然后保存

定义实体在eclipse工具中定义,定义好后讲要导入的实体打成jar包,然后倒入规则库

 

 

然后进入资产资料库

Jar包文件:

 

 

 

由于我们导出的jar包不是标准的maven jar包所以会出如下错误:

 

此时我们点击确定,手动指定GAV,如下图:

 

然后点击上传图标,上传成功!

此时如果外部倒入的jar包能够使用还要进行如下操作:

重新打开刚才创建的项目:

 

 

 

 

 

然后点击保存按钮!

1.2.2规则文件-决策表创建

该文件的创建有两种第一种向导型决策表,第二种excel电子表格决策表

第一种向导型决策表:

创建完后点击如下按钮可以验证上面倒入外部jar是否成功:如果可以看到倒入jar包内的class则表示成功!

 

 

点击添加图标可以增加condition和action列以及规则的其他属性信息

 

 

 

第一个是添加规则可选属性用的,第二个和第三个是添加condition用的区别:第三个是*编写的格式,选中下面的复选框后,可以有更多的可选项,最后一个是添加action用的,选中添加*格式可以自定义编辑

向导型决策表condition和action事例

 

 

 

第二种excel电子表格决策表:

 

 

 

选中已经写好的电子表格上传即可!

1.3 规则部署

1.3.1构建项目

 

1.3.2创建容器

 

 

 

 

点击链接后如果出现如下结果证明容器启动成功:

 

1.4 规则调运

如果需要调用容器内部运行的规则,通知后台管理人员,管理员会给你如下参数

Property配置文件如下:

#服务路径

SERVICE_URL=http://127.0.0.1:20882/rule/exec

#非向导型决策表

PK_SECRET_KEY=a2llLXNlcnZlcjF0ZXN0X2RjdGFibGUxNDY5NDMxNjMzMjM3

#服务名称

PK_SERVER_NAME=kie-server1

#非向导型决策表容器

PK_CONTAINER_NAME=test_dctable

 

调用代码如下:

package com.paas.service.modules.brm.controller;

 

import java.net.MalformedURLException;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

 

import javax.servlet.http.HttpServletRequest;

 

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

 

import com.alibaba.dubbo.common.json.JSON;

import com.alibaba.fastjson.JSONObject;

import com.caucho.hessian.client.HessianProxyFactory;

import com.paas.base.modules.utils.config.Global;

import com.paas.service.modules.brm.service.dubbo.IRuleMgrDubboService;

import com.yihe.model.dctable.pkpric.CarType;

import com.yihe.model.dctable.pkpric.ParkType;

import com.yihe.model.dctable.pkpric.PkPricing;

import com.yihe.model.dctable.pkpric.RegionType;

 

@Controller

@RequestMapping("/pkpricing")

public class PkPricingController {

    protected static final Log logger = LogFactory.getLog(PkPricingController.class);

    private static final String PK_SECRET_KEY = Global.getConfig("PK_SECRET_KEY");;

    private static final String PK_SERVER_NAME = Global.getConfig("PK_SERVER_NAME");;

   private static final String PK_CONTAINER_NAME = Global.getConfig("PK_CONTAINER_NAME");;

    static IRuleMgrDubboService ruleMgrDubboService = null;

    static {

       final String SERVICE_URL = Global.getConfig("SERVICE_URL");

       HessianProxyFactory factory = new HessianProxyFactory();

       try {

           ruleMgrDubboService = (IRuleMgrDubboService) factory.create(IRuleMgrDubboService.class, SERVICE_URL);

       } catch (MalformedURLException e) {

           e.printStackTrace();

       }

    }

 

    /**

     *

     * @param request

     * @return

     */

    @RequestMapping("/index")

    public String index(HttpServletRequest request, Model model) {

       return "/drools/pkpricing/pkpricing-manage";

    }

 

    @SuppressWarnings("unchecked")

    @RequestMapping("/calculation")

    @ResponseBody

    public String saveOrUpdate(HttpServletRequest request) {

       List<Object> list = new ArrayList<Object>();

       ParkType parkType = new ParkType(request.getParameter("parkCode"), request.getParameter("parkName"));

       list.add(parkType);

       RegionType regionType = new RegionType(request.getParameter("regionCode"), request.getParameter("regionName"));

       list.add(regionType);

       CarType carType = new CarType(request.getParameter("carCode"), request.getParameter("carName"));

       list.add(carType);

       PkPricing pkPricing = new PkPricing();

       pkPricing.setHours(Double.parseDouble(request.getParameter("hours")));

       list.add(pkPricing);

       Object[] paramArray = list.toArray(new Object[list.size()]);

 

       JSONObject json = new JSONObject();

       json.put("status", 1);

       try {

           String result = ruleMgrDubboService.exec(PK_SECRET_KEY, PK_SERVER_NAME, PK_CONTAINER_NAME, null,

                  paramArray, null);

           System.out.println(result);

           Map<String, Object> resultMap = JSON.parse(result, Map.class);

           if (!resultMap.get("code").toString().equals("1"))

              json.put("msg", resultMap.get("msg").toString());

           else {

              Map<String, Object> map = (Map<String, Object>) resultMap.get("data");

              List<Map<String, Object>> plist = (List<Map<String, Object>>) map.get("GET_OBJECTS");

              Map<String, Object> lastMap = plist.get(plist.size() - 1);

              json.put("totalFee", lastMap.get("totalFee"));

              json.put("status", 0);

           }

 

       } catch (Exception e) {

           logger.error("", e);

           json.put("status", 1);

       }

       return json.toJSONString();

    }

 

}

注意此处的:实体的包路径必需和规则文件中的实体的路径完全一致否则调用失败!

 

风险控制应用

 

流程引擎(BPM)应用

 

附录

规则文件结构

 

每一条规则都有名称. 
每一条规则都有属性(lock-on-active等) 
When里写的是LHS(Left Hand Side,左手边),等同于IF里的条件判断.左手边是Drools自己的语法规则,详见Drools的文档。
Then里写的是RHS(Right Hand Side,右手边),等同于IF里的执行语句.右手边支持多种语言(Java,Pthyon,Groovy等)。

规则文件示例

package com.yihe.test2;//指定包名,类似命名空间

 

import java.util.*; //引入jar包

 

dialect "java"//设置规则所使用的语言

declare User//自定义对象

       name:String

       id:String

       age:int

       birthDate:java.util.Date

end

 

rule "rule1" //规则名

    no-loop true//只执行一次

when 

         //条件

         $paramMap : Map(this['id'] == '1')

then 

         //业务操作

         System.out.println ( "执行规则: "+drools.getRule().getName());

         System.out.println ( "id:"+$paramMap.get("id"));

         System.out.println("name:"+$paramMap.get("name"));

         $paramMap.put("result","8888");

         List _resultList = new ArrayList();

              _resultList.add("999999");

              insert(_resultList);

end

 

DefineObject对象(自定义对象)

import java.util.Map;

 

public class DefineObject {

   /** 规则文件包名 */

   private String packageName;

   /** 对象名 */

   private String objectName;

   /** 实例数据 */

   private Map<String, Object> instanceData;

 

   public String getPackageName() {

      return packageName;

   }

 

   public void setPackageName(String packageName) {

      this.packageName = packageName;

   }

 

   public String getObjectName() {

      return objectName;

   }

 

   public void setObjectName(String objectName) {

      this.objectName = objectName;

   }

 

   public Map<String, Object> getInstanceData() {

      return instanceData;

   }

 

   public void setInstanceData(Map<String, Object> instanceData) {

      this.instanceData = instanceData;

   }

 

   public DefineObject() {

   }

 

   /**

    *

    * @param packageName

    *            规则文件包名

    * @param objectName

    *            对象名

    * @param instanceData

    *            实例数据

    */

   public DefineObject(String packageName, String objectName,

         Map<String, Object> instanceData) {

      super();

      this.packageName = packageName;

      this.objectName = objectName;

      this.instanceData = instanceData;

   }

}

 

 

转载于:https://my.oschina.net/fxdemon/blog/1603927