前后端分目录

This commit is contained in:
andywang
2022-07-14 12:55:31 +08:00
parent cd72c43d62
commit bb8cf90f53
1155 changed files with 47237 additions and 14446 deletions

View File

@@ -0,0 +1,15 @@
<?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">
<parent>
<artifactId>ddp-enginex</artifactId>
<groupId>com.fibo.ddp</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ddp-enginex-runner-node</artifactId>
</project>

View File

@@ -0,0 +1,120 @@
package com.fibo.ddp.enginex.runner.canal;
import com.fibo.ddp.common.dao.canal.TableEnum;
import com.fibo.ddp.common.dao.datax.datasource.SimpleMapper;
import com.fibo.ddp.common.service.redis.RedisManager;
import com.fibo.ddp.common.service.redis.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/cache")
public class CacheController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private SimpleMapper simpleMapper;
@Autowired
private RedisManager redisManager;
@RequestMapping(value = "initCache", method = RequestMethod.GET)
public void initCache() {
logger.info("===================== 缓存初始化开始 =====================");
long start = System.currentTimeMillis();
// 遍历表
for (TableEnum tableEnum : TableEnum.values()) {
String tableName = tableEnum.getTableName();
logger.info("===================== 开始初始化缓存表[{}] =====================", tableName);
String sqlStr = "select * from " + tableName;
Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("sqlStr", sqlStr);
List<LinkedHashMap<String, Object>> result = simpleMapper.customSelect(parameterMap);
// 遍历行
for (LinkedHashMap<String, Object> map : result) {
row(tableEnum, map);
}
logger.info("===================== 结束初始化缓存表[{}],共[{}]条数据 =====================", tableName, result.size());
}
long end = System.currentTimeMillis();
logger.info("===================== 缓存初始化成功!!耗时:{}ms =====================", (end - start));
}
private void row(TableEnum tableEnum, LinkedHashMap<String, Object> map) {
String tableName = tableEnum.getTableName();
String primaryKey = null;
String foreignKey = null;
if (StringUtils.isNotBlank(tableEnum.getPrimaryId())) {
String primaryId = map.get(tableEnum.getPrimaryId()).toString();
primaryKey = RedisUtils.getPrimaryKey(tableName, primaryId);
}
if (StringUtils.isNotBlank(tableEnum.getForeignId())) {
Object obj = map.get(tableEnum.getForeignId());
if (obj != null && !"".equals(obj.toString())) {
String foreignId = obj.toString();
foreignKey = RedisUtils.getForeignKey(tableName, foreignId);
}
}
if (StringUtils.isNotBlank(primaryKey)) {
// 遍历列
for (String field : map.keySet()) {
String value = map.get(field) == null ? null : map.get(field).toString();
setColumnCache(primaryKey, field, value);
}
}
if (StringUtils.isNotBlank(foreignKey)) {
setForeignKeyCache(primaryKey, foreignKey);
}
// 指标表特殊处理
dealSpecialTable(tableName, map);
}
private void setColumnCache(String primaryKey, String field, String value) {
logger.info("开始主键缓存设置, primaryKey:{}, field:{}, value:{}", primaryKey, field, value);
redisManager.hset(primaryKey, field, value);
logger.info("结束主键缓存设置, primaryKey:{}, field:{}, value:{}", primaryKey, field, value);
}
private void setForeignKeyCache(String primaryKey, String foreignKey) {
logger.info("开始外键缓存设置, primaryKey:{}, foreignKey:{}", primaryKey, foreignKey);
redisManager.sadd(foreignKey, primaryKey);
logger.info("结束外键缓存设置, primaryKey:{}, foreignKey:{}", primaryKey, foreignKey);
}
private void dealSpecialTable(String tableName, LinkedHashMap<String, Object> map) {
if(tableName.equals(TableEnum.T_FIELD.getTableName())){
String fieldEn = "field_en:" + map.get("organ_id") + ":" + map.get("field_en");
String fieldEnKey = RedisUtils.getPrimaryKey(tableName, fieldEn);
String fieldCn = "field_cn:" + map.get("organ_id") + ":" + map.get("field_cn");
String fieldCnKey = RedisUtils.getPrimaryKey(tableName, fieldCn);
for (String field : map.keySet()) {
String value = map.get(field) == null ? null : map.get(field).toString();
setColumnCache(fieldEnKey, field, value);
setColumnCache(fieldCnKey, field, value);
}
}
}
}

View File

@@ -0,0 +1,254 @@
package com.fibo.ddp.enginex.runner.canal;
import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.alibaba.otter.canal.protocol.Message;
import com.fibo.ddp.common.dao.canal.TableEnum;
import com.fibo.ddp.common.service.redis.RedisManager;
import com.fibo.ddp.common.service.redis.RedisUtils;
import com.fibo.ddp.common.utils.constant.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Optional;
/**
* Canal数据同步
* 实现ApplicationRunner接口springboot启动成功后会执行run方法
*/
@Component
public class CanalClient implements ApplicationRunner {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final static int BATCH_SIZE = 1000;
@Autowired
private RedisManager redisManager;
// canal缓存同步是否开启
@Value("${switch.canal.cache}")
private String canalCacheSwitch;
// canal主机地址
@Value("${canal.hostname}")
private String canalHostName;
// canal端口
@Value("${canal.port}")
private int canalPort;
@Override
public void run(ApplicationArguments args) throws Exception {
if(Constants.switchFlag.OFF.equals(canalCacheSwitch)){
return;
}
// 创建链接
CanalConnector connector = CanalConnectors.newSingleConnector(
new InetSocketAddress(canalHostName, canalPort),
"example", "", "");
try {
//打开连接
connector.connect();
//订阅数据库表,全部表
connector.subscribe(".*\\..*");
//回滚到未进行ack的地方下次fetch的时候可以从最后一个没有ack的地方开始拿
connector.rollback();
while (true) {
logger.info("canal数据同步监听中...");
// 获取指定数量的数据
Message message = connector.getWithoutAck(BATCH_SIZE);
//获取批量ID
long batchId = message.getId();
//获取批量的数量
int size = message.getEntries().size();
//如果没有数据
if (batchId == -1 || size == 0) {
try {
//线程休眠2秒
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//如果有数据,处理数据
printEntry(message.getEntries());
}
//进行 batch id 的确认。确认之后,小于等于此 batchId 的 Message 都会被确认。
connector.ack(batchId);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
connector.disconnect();
}
}
/**
* 解析binlog获得的实体类信息
*/
private void printEntry(List<CanalEntry.Entry> entrys) {
for (CanalEntry.Entry entry : entrys) {
if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND) {
//开启/关闭事务的实体类型,跳过
continue;
}
String tableName = entry.getHeader().getTableName();
TableEnum tableEnum = TableEnum.getByTableName(tableName);
if(tableEnum == null){
// 没有在枚举中定义的表,跳过
continue;
}
//RowChange对象包含了一行数据变化的所有特征
//比如isDdl 是否是ddl变更操作 sql 具体的ddl sql beforeColumns afterColumns 变更前后的数据字段等等
CanalEntry.RowChange rowChage;
try {
rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
} catch (Exception e) {
throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(), e);
}
//获取操作类型insert/update/delete类型
CanalEntry.EventType eventType = rowChage.getEventType();
//打印Header信息
logger.info(String.format("============= binlog[%s:%s] , name[%s,%s] , eventType : %s =============",
entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
eventType));
//判断是否是DDL语句
if (rowChage.getIsDdl()) {
logger.info("============= isDdl: true,sql:" + rowChage.getSql());
}
//获取RowChange对象里的每一行数据
for (CanalEntry.RowData rowData : rowChage.getRowDatasList()) {
//如果是删除语句
if (eventType == CanalEntry.EventType.DELETE) {
row(rowData.getBeforeColumnsList(), tableName);
//如果是新增语句
} else if (eventType == CanalEntry.EventType.INSERT) {
row(rowData.getAfterColumnsList(), tableName);
//如果是更新的语句
} else {
//变更前的数据
// printColumn(rowData.getBeforeColumnsList(), tableName);
//变更后的数据
row(rowData.getAfterColumnsList(), tableName);
}
}
}
}
private void row(List<CanalEntry.Column> columns, String tableName) {
Optional<CanalEntry.Column> keyColumn = columns.stream().filter(item -> item.getIsKey()).findFirst();
if(keyColumn.isPresent()){
// 获取主键id
String id = keyColumn.get().getValue();
// 拼接主键key
String key = RedisUtils.getPrimaryKey(tableName, id);
// 拼接外键key
String foreignKey = null;
// 子表的redis key需要拼接上主表的id
TableEnum tableEnum = TableEnum.getByTableName(tableName);
if(tableEnum != null){
Optional<CanalEntry.Column> foreignKeyColumn = columns.stream().filter(item -> item.getName().equals(tableEnum.getForeignId())).findFirst();
if(foreignKeyColumn.isPresent()){
String foreignKeyValue = foreignKeyColumn.get().getValue();
foreignKey = RedisUtils.getForeignKey(tableName, foreignKeyValue);
}
}
for (CanalEntry.Column column : columns) {
// 更新发生改变的字段缓存
setUpdatedColumnCache(column, key, foreignKey);
}
// 指标表特殊处理
dealSpecialTable(columns, tableName);
}
}
private void setUpdatedColumnCache(CanalEntry.Column column, String key, String foreignKey){
if(column.getUpdated()) {
logger.info("开始主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
redisManager.hset(key, column.getName(), column.getValue());
logger.info("结束主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
if(foreignKey != null){
logger.info("开始外键缓存更新, {}, {}", key, foreignKey);
redisManager.sadd(foreignKey, key);
logger.info("结束外键缓存更新, {}, {}", key, foreignKey);
}
}
}
private void setAllColumnCache(CanalEntry.Column column, String key){
logger.info("开始主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
redisManager.hset(key, column.getName(), column.getValue());
logger.info("结束主键缓存更新, {}, {}, {}", key, column.getName(), column.getValue());
}
private void dealSpecialTable(List<CanalEntry.Column> columns, String tableName){
if(tableName.equals(TableEnum.T_FIELD.getTableName())){
String organ_id = null;
String field_en = null;
String field_cn = null;
for (CanalEntry.Column column : columns) {
String name = column.getName();
switch (name) {
case "organ_id":
organ_id = column.getValue();
break;
case "field_en":
field_en = column.getValue();
break;
case "field_cn":
field_cn = column.getValue();
break;
default:
break;
}
}
String fieldEn = "field_en:" + organ_id + ":" + field_en;
String fieldEnKey = RedisUtils.getPrimaryKey(tableName, fieldEn);
String fieldCn = "field_cn:" + organ_id + ":" + field_cn;
String fieldCnKey = RedisUtils.getPrimaryKey(tableName, fieldCn);
// 如果field_en或field_cn发生变化则对应的key为新生成的需要保存所有字段缓存
Optional<CanalEntry.Column> fieldEnOptional = columns.stream().filter(item -> item.getName().equals("field_en") && item.getUpdated()).findFirst();
Optional<CanalEntry.Column> fieldCnOptional = columns.stream().filter(item -> item.getName().equals("field_cn") && item.getUpdated()).findFirst();
for (CanalEntry.Column column : columns) {
if(fieldEnOptional.isPresent()){
// 更新所有字段缓存
setAllColumnCache(column, fieldEnKey);
} else {
// 更新发生改变的字段缓存
setUpdatedColumnCache(column, fieldEnKey, null);
}
if(fieldCnOptional.isPresent()){
setAllColumnCache(column, fieldCnKey);
} else {
setUpdatedColumnCache(column, fieldCnKey, null);
}
}
}
}
}

View File

@@ -0,0 +1,60 @@
package com.fibo.ddp.enginex.runner.ksession;
import com.fibo.ddp.common.service.redis.RedisManager;
import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.*;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* kSession工厂类
*/
@Component
public class KSessionFactory extends BaseKeyedPooledObjectFactory<String, StatefulKnowledgeSession> {
@Autowired
private RedisManager redisManager;
@Override
public StatefulKnowledgeSession create(String key) throws Exception {
StatefulKnowledgeSession kSession = null;
try {
String ruleString = redisManager.get(key);
if(ruleString == null){
throw new Exception("create kSession fail, key is "+ key + ", ruleString is null");
}
long start = System.currentTimeMillis();
KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
kb.add(ResourceFactory.newByteArrayResource(ruleString.getBytes("utf-8")), ResourceType.DRL);
KnowledgeBuilderErrors errors = kb.getErrors();
for (KnowledgeBuilderError error : errors) {
System.out.println(error);
}
KnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
kBase.addKnowledgePackages(kb.getKnowledgePackages());
kSession = kBase.newStatefulKnowledgeSession();
long end = System.currentTimeMillis();
System.out.println("------------------drools kSession创建耗时" + (end - start) + " ----------------------");
} catch (Exception e) {
throw e;
}
return kSession;
}
@Override
public PooledObject<StatefulKnowledgeSession> wrap(StatefulKnowledgeSession kSession) {
return new DefaultPooledObject<StatefulKnowledgeSession>(kSession);
}
public void setRedisManager(RedisManager redisManager) {
this.redisManager = redisManager;
}
}

View File

@@ -0,0 +1,67 @@
package com.fibo.ddp.enginex.runner.ksession;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.drools.runtime.StatefulKnowledgeSession;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* kSession连接池
*/
@Component
public class KSessionPool implements InitializingBean {
private GenericKeyedObjectPool<String, StatefulKnowledgeSession> pool;
@Autowired
private KSessionFactory kSessionFactory;
/**
* 初始化方法
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
initPool();
}
/**
* 初始化连接池
* @return
* @throws Exception
*/
public void initPool() throws Exception {
GenericKeyedObjectPoolConfig poolConfig = new GenericKeyedObjectPoolConfig();
poolConfig.setMaxTotalPerKey(200);
poolConfig.setMaxIdlePerKey(50);
poolConfig.setMinIdlePerKey(5);
poolConfig.setMaxTotal(2000);
this.pool = new GenericKeyedObjectPool(kSessionFactory, poolConfig);
}
/**
* 获取一个连接对象
* @return
* @throws Exception
*/
public StatefulKnowledgeSession borrowObject(String key) throws Exception {
return pool.borrowObject(key);
}
/**
* 归还一个连接对象
* @param ftpClient
*/
public void returnObject(String key, StatefulKnowledgeSession kSession) {
if(kSession != null){
pool.returnObject(key, kSession);
}
}
public void setkSessionFactory(KSessionFactory kSessionFactory) {
this.kSessionFactory = kSessionFactory;
}
}

View File

@@ -0,0 +1,26 @@
package com.fibo.ddp.enginex.runner.node;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import java.util.Map;
/**
* 引擎节点执行
*/
public interface EngineRunnerNode {
/**
* 获取节点所需的指标
* @param engineNode
* @param inputParam
*/
void getNodeField(EngineNode engineNode, Map<String, Object> inputParam);
/**
* 执行节点逻辑
* @param engineNode
* @param inputParam
* @param outMap
*/
void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap);
}

View File

@@ -0,0 +1,36 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 聚合节点
*/
@Service
public class AggregationNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
logger.info("start【执行聚合节点】AggregationNode.runNode engineNode:{},inputParam:{},outMap:{}"
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
// 直接返回下一个节点
outMap.put("nextNode", engineNode.getNextNodes());
if (engineNode != null && engineNode.getSnapshot() != null) {
outMap.put("nodeSnapshot", engineNode.getSnapshot());
}
}
}

View File

@@ -0,0 +1,286 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.dao.datax.datamanage.CustListMapper;
import com.fibo.ddp.common.dao.datax.datamanage.FieldMapper;
import com.fibo.ddp.common.dao.strategyx.listlibrary.TblColumnMapper;
import com.fibo.ddp.common.model.datax.datamanage.Field;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.model.strategyx.listlibrary.ListDb;
import com.fibo.ddp.common.model.strategyx.listlibrary.TblColumn;
import com.fibo.ddp.common.model.strategyx.strategyout.StrategyOutput;
import com.fibo.ddp.common.service.common.runner.RunnerSessionManager;
import com.fibo.ddp.common.service.common.runner.SessionData;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
import com.fibo.ddp.common.service.strategyx.listlibrary.ListDbService;
import com.fibo.ddp.common.service.strategyx.strategyout.StrategyOutputService;
import com.fibo.ddp.common.utils.constant.strategyx.StrategyType;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
@Service
public class BlackOrWhiteNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CommonService commonService;
@Autowired
private TblColumnMapper tblColumnMapper;
@Resource
private ListDbService listDbService;
@Resource
public FieldMapper fieldMapper;
@Resource
public CustListMapper custListMapper;
@Resource
private StrategyOutputService outputService;
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
return ExecuteUtils.getExecuteIdList(engineNode, "listDbId");
}
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
List<Long> list = getExecuteVersionIdList(engineNode);
List<Long> fieldIds = new ArrayList<>();
for (Long l : list) {
fieldIds.addAll(listDbService.getNodeFieldIds(l));
}
commonService.getFieldByIds(fieldIds, inputParam);
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
//监控中心-节点信息快照记录
if(engineNode!=null && engineNode.getNodeJson()!=null){
outMap.put("nodeSnapshot",engineNode.getNodeJson());
}
inputParam.put("nodeId", engineNode.getNodeId());
inputParam.put("nodeName", engineNode.getNodeName());
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode", engineNode);
nodeInfo.put("nodeId", engineNode.getNodeId());
nodeInfo.put("nodeName", engineNode.getNodeName());
nodeInfo.put("nodeType", engineNode.getNodeType());
outMap.put("nodeInfo", nodeInfo);
//新代码
String hitKey = "" + engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_size";
List<Long> list = getExecuteVersionIdList(engineNode);
List<ListDb> hitListDb = new ArrayList<>();
//创建内部多选的名单库结果数组
JSONArray resultJsonArray = new JSONArray();
JSONArray strategySnapshot = new JSONArray();
for (Long id : list) {
ListDb listDb = listDbService.queryById(id);
//监控中心 == 策略层面快照信息
if (listDb != null && listDb.getSnapshot() != null) {
strategySnapshot.add(listDb.getSnapshot());
}
boolean isfalg = this.executeListDb(listDb, inputParam, outMap,resultJsonArray);
if (isfalg) {
hitListDb.add(listDb);
}
}
//监控中心==》策略层面快照信息记录
outMap.put("strategySnapshot",strategySnapshot);
//构造节点信息
JSONObject jsonObject = new JSONObject();
jsonObject.put("nodeId", engineNode.getNodeId());
jsonObject.put("nodeName", engineNode.getNodeName());
jsonObject.put("resultList", resultJsonArray);
//判断是否出现过同类型的,如果出现过则获取并且增加内容,如果没有则需要构建名单库类型的节点信息
if (outMap.containsKey("blackJson")) {
//如果出现过黑名单则从黑名单接送中获取
JSONObject blackJson = (JSONObject) outMap.get("blackJson");
JSONArray resultJson = blackJson.getJSONArray("resultJson");
resultJson.add(jsonObject);
} else {
JSONObject nodeResult = new JSONObject();
nodeResult.put("resultType", 5);
JSONArray resultJson = new JSONArray();
resultJson.add(jsonObject);
nodeResult.put("resultJson",resultJson);
outMap.put("blackJson", nodeResult);
}
// nodeResult.put("resultJson", resultJsonArray);
// outMap.put("blackJson", nodeResult);
// outMap.put("nodeResult", nodeResult);
inputParam.put(hitKey, hitListDb.size());
//处理终止条件判断中选择的名单库
long count = handlerResultCount(engineNode, hitListDb);
this.terminalCondition(engineNode, inputParam, outMap, count);
}
private boolean executeListDb(ListDb listDb, Map<String, Object> inputParam, Map<String, Object> outMap,JSONArray resultJsonArray) {
SessionData sessionData = RunnerSessionManager.getSession();
Long organId = sessionData.getOrganId();
JSONObject resultJson = new JSONObject();
Integer matchs = 0;
Integer revMatchs = 0; //模糊查询时反向匹配
// JSONArray strategySnopshot = new JSONArray();
Long listDbId = listDb.getId();
// if (listDb.getSnapshot() != null) {
//
// strategySnopshot.add(listDb.getSnapshot());
// }
inputParam.put("listDb", listDb);
ListDb version = listDb;
String queryKeyArray[] = listDb.getQueryField().split(",");
if (queryKeyArray.length > 0) {
Integer queryType = version.getQueryType();//and1or0
Integer matchType = version.getMatchType();//精确匹配1模糊匹配0
String queryKey = ""; // t1 like '%t1%'
String revQueryKey = ""; // 反向模糊匹配 instr('高档洗浴消费',t1) t1行业字段 eg.'洗浴'
String tableName = "organ" + "_" + organId + "_" + listDb.getListType() + "_" + listDbId;
inputParam.put("tableName", tableName);
inputParam.put("schemaName", getDbName());
//获取名单库的匿名字段与注释的关系
List<TblColumn> columnList = tblColumnMapper.getColumnList(inputParam);
//字段id转匿名字段名准备待查字段条件
Integer loc = 0;
List<String> tableColumn = Arrays.asList(version.getTableColumn().split(","));
int k = 0;
for (int j = 0; j < queryKeyArray.length; j++) {
k = tableColumn.indexOf(queryKeyArray[j]);
if (k < 0) {
continue;
}
Field field = fieldMapper.selectById(queryKeyArray[j]);
String fieldEn = field.getFieldEn(); //age
String columnKey = "t" + k;
for (TblColumn tblColumn : columnList) {
String colName = tblColumn.getColName(); //t5
String paramValue = inputParam.get(fieldEn).toString();
if (columnKey.equals(colName)) {
if (paramValue == null || paramValue.equals("")) {
continue ; //数据项缺失导致无法命中,默认返回没命中
} else {
loc += 1;
if (matchType == 1) {
if (loc > 1 && queryType == 1) {
queryKey += " and ";
} else if (loc > 1 && queryType == 0) {
queryKey += " or ";
}
queryKey += colName + " = '" + paramValue + "'";
} else if (matchType == 0) { //模糊匹配
if (loc > 1 && queryType == 1) {
queryKey += " and ";
} else if (loc > 1 && queryType == 0) {
queryKey += " or ";
revQueryKey += " + ";
}
//正向模糊搜索
queryKey += colName + " like " + "'%" + paramValue + "%'"; // t5 like '%36岁%'
//反向模糊搜索
revQueryKey += "max(instr('" + paramValue + "'," + colName + "))";
}
}
}
}
}
inputParam.put("queryKey", queryKey);
inputParam.put("revQueryKey", revQueryKey);
}
matchs += custListMapper.findByQueryKey(inputParam);
if (!"".equals(inputParam.get("revQueryKey"))) {
revMatchs = custListMapper.revFindByQueryKey(inputParam);
}
if (revMatchs == null){
revMatchs = 0;
}
inputParam.put(listDb.getResultFieldEn(), "未命中");
List<JSONObject> fieldList = new ArrayList<>();
JSONObject hitResult = new JSONObject();
hitResult.put(listDb.getResultFieldEn(), "未命中");
// resultJson.put("nodeId", inputParam.get("nodeId").toString());
// resultJson.put("nodeName", inputParam.get("nodeName").toString());
resultJson.put("listDbId", listDb.getId());
resultJson.put("listDbName", listDb.getListName());
resultJson.put("listDbType", listDb.getListType());
if (null != listDb.getListDesc()) {
resultJson.put("desc", listDb.getListDesc());
}
resultJson.put("fieldList", fieldList);
resultJsonArray.add(resultJson);
if (matchs + revMatchs > 0) {
inputParam.put(listDb.getResultFieldEn(), "命中");
hitResult.put(listDb.getResultFieldEn(), "命中");
List<JSONObject> jsonObjects = outputService.setOutput(new StrategyOutput(Long.valueOf(listDbId.toString()), StrategyType.LIST_DB), inputParam);
fieldList.add(hitResult);
fieldList.addAll(jsonObjects);
// outMap.put("black", listDb);
return true;
} else {
fieldList.add(hitResult);
}
//监控中心==》策略层面记录策略的快照信息
// JSONObject strategyObject = new JSONObject();
// strategyObject.put("strategySnopshot", strategySnopshot);
// outMap.put("strategySnopshot", strategyObject);
return false;
}
/**
* 根据传入数据监测是否命中黑名单
*
* @param paramMap
* @return
* @see
*/
public boolean findByQueryKey(Map<String, Object> paramMap, Map<String, Object> outmap, Integer type, EngineNode engineNode) {
return false;
}
private String getDbName() {
return "riskmanage";
}
private long handlerResultCount(EngineNode engineNode,List<ListDb> hitListDb){
JSONObject jsonObject = JSON.parseObject(engineNode.getNodeJson());
JSONArray selectedRule = jsonObject.getJSONObject("terminationInfo").getJSONArray("selectedRule");
List<Long> selectedListDbIds = new ArrayList<>();
if (selectedRule!=null&&selectedRule.size()>0){
for (Object o : selectedRule) {
if (o==null){
continue;
}
Long id = JSON.parseObject(JSON.toJSONString(o)).getLong("id");
if (id==null){
continue;
}
selectedListDbIds.add(id);
}
}
long count = hitListDb.stream().filter(item -> selectedListDbIds.contains(item.getId())).count();
return count;
}
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, Object executeResult) {
String sizeKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_size";
Map<String, Object> map = new HashMap<>();
map.put(sizeKey, executeResult);
ExecuteUtils.terminalCondition(engineNode, inputParam, outMap, map);
}
}

View File

@@ -0,0 +1,44 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 冠军挑战节点
*/
@Service
public class ChampionChallengeNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
logger.info("start【执行冠军挑战节点】ChampionChallengeNode.runNode engineNode:{},inputParam:{},outMap:{}"
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
if (engineNode != null && engineNode.getSnapshot() != null) {
outMap.put("nodeSnapshot", engineNode.getSnapshot());
}
JSONArray jsonArray = JSONArray.parseArray(engineNode.getNodeJson());
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
int champion = jsonObject.getIntValue("champion");
// 返回冠军分支对应的下一个节点
if(champion == 1){
outMap.put("nextNode", jsonObject.getString("nextNode"));
break;
}
}
}
}

View File

@@ -0,0 +1,82 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.Engine;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.service.common.runner.RunnerSessionManager;
import com.fibo.ddp.common.service.common.runner.SessionData;
import com.fibo.ddp.common.service.enginex.risk.EngineService;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class ChildEngineNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// @Autowired
// private EngineApiService engineApiService;
@Autowired
public EngineService engineService;
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
SessionData sessionData = RunnerSessionManager.getSession();
Long organId = sessionData.getOrganId();
Integer reqType = sessionData.getReqType();
Long childEngineId = Long.valueOf(engineNode.getNodeJson());
Map<String, Object> map = new HashMap<>();
map.put("fields",inputParam);
map.put("engineId", childEngineId);
map.put("organId",organId);
map.put("reqType",reqType);
// String result = engineApiService.engineApi(map);
String result = null;
String engineResult = "";
JSONObject jsonObject = JSONObject.parseObject(result);
if (jsonObject.getString("status").equals("0x0000")&&jsonObject.getString("result")!=null) {
engineResult = jsonObject.getString("result");
} else {
logger.error("子引擎执行失败, childEngineId:{},result:{}", childEngineId, result);
}
Engine engineVo = engineService.getEngineById(childEngineId);
//监控中心--节点信息记录(不需要监控策略层面的监控)
outMap.put("nodeSnapshot",engineVo);
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode",engineNode);
nodeInfo.put("nodeId",engineNode.getNodeId());
nodeInfo.put("nodeName",engineNode.getNodeName());
nodeInfo.put("nodeType",engineNode.getNodeType());
outMap.put("nodeInfo",nodeInfo);
jsonObject.put("nodeId", engineNode.getNodeId());
jsonObject.put("nodeName", engineNode.getNodeName());
jsonObject.put("engineId", engineVo.getId());
jsonObject.put("engineName", engineVo.getName());
//监控中心====》输出结果写入Hbase
outMap.put("nodeResult",jsonObject);
if (outMap.containsKey("childEngineJson")) {
JSONArray resultJson = (JSONArray) outMap.get("childEngineJson");
resultJson.add(jsonObject);
} else {
JSONArray resultJson = new JSONArray();
resultJson.add(jsonObject);
outMap.put("childEngineJson", resultJson);
}
String key = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_" + engineNode.getNodeJson() + "_result";
inputParam.put(key, engineResult);
}
}

View File

@@ -0,0 +1,144 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.utils.util.runner.JevalUtil;
import com.fibo.ddp.common.utils.util.runner.jeval.EvaluationException;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 决策选项节点
*/
@Service
public class DecisionOptionsNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CommonService commonService;
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
logger.info("start【获取决策选项节点指标】DecisionOptionsNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
JSONObject jsonObject = JSONObject.parseObject(engineNode.getNodeScript());
JSONArray array = jsonObject.getJSONArray("input");
List<Long> ids = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
JSONObject input = array.getJSONObject(i);
Object fieldId = input.get("field_id");
if(fieldId != null && !"".equals(fieldId.toString())){
ids.add(Long.valueOf(fieldId.toString()));
}
}
commonService.getFieldByIds(ids, inputParam);
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
//监控信息--节点信息记录(不需要策略层面的监控)
outMap.put("nodeSnapshot",JSON.parseObject(engineNode.getNodeJson()));
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode",engineNode);
nodeInfo.put("nodeId",engineNode.getNodeId());
nodeInfo.put("nodeName",engineNode.getNodeName());
nodeInfo.put("nodeType",engineNode.getNodeType());
outMap.put("nodeInfo",nodeInfo);
JSONObject jsonObject = JSONObject.parseObject(engineNode.getNodeScript());
JSONArray inputArray = jsonObject.getJSONArray("input");
List<JSONObject> inputList = JSONObject.parseArray(JSONObject.toJSONString(jsonObject.getJSONArray("input")), JSONObject.class);
JSONArray conditionArray = jsonObject.getJSONArray("conditions");
JSONObject outputJson = jsonObject.getJSONObject("output");
// 变量值转义
Map<String, Object> variablesMap = new HashMap<>();
for (int i = 0; i < inputArray.size(); i++) {
String input = inputArray.get(i).toString();
JSONObject inputField = JSONObject.parseObject(input);
String field_code = inputField.getString("field_code");
Map<String, Integer> fieldsMap = new HashMap<>();
fieldsMap.put(field_code, inputField.getInteger("valueType"));
variablesMap.put(field_code, inputParam.get(field_code));
variablesMap = JevalUtil.convertVariables(fieldsMap, variablesMap);
}
// 默认值处理
String dicisionResult ="";
String defaultValue = outputJson.getString("defaultValue");
if (StringUtils.isNotBlank(defaultValue)){
dicisionResult = defaultValue;
}
// 决策条件判断
if(conditionArray != null && conditionArray.size() > 0){
for (int i = 0; i < conditionArray.size(); i++) {
JSONObject formulaJson = JSONObject.parseObject(conditionArray.getString(i));
try {
boolean outfieldvalue = JevalUtil.evaluateBoolean(formulaJson.getString("formula"), variablesMap);
if (outfieldvalue) {
dicisionResult = formulaJson.getString("result");
// 输出结果计算
String result = formulaJson.getString("result");
if(result.contains("{") && result.contains("}")){
String expression = result;
Pattern pattern = Pattern.compile("\\{[a-zA-Z0-9_\u4e00-\u9fa5()-]+\\}");
Matcher matcher = pattern.matcher(expression);
while (matcher.find()) {
String asName = matcher.group(0).replace("{", "").replace("}", "");
Optional<JSONObject> inputObj = inputList.stream().filter(item -> asName.equals(item.getString("asName"))).findFirst();
if(inputObj.isPresent()){
String field_code = inputObj.get().getString("field_code");
expression = expression.replaceAll(asName, field_code);
}
}
expression = expression.replaceAll("\\{", "#{");
Double calResult = JevalUtil.evaluateNumric(expression, variablesMap);
dicisionResult = calResult.toString();
}
break;
}
} catch (EvaluationException e) {
e.printStackTrace();
logger.error("请求异常", e);
}
}
}
Map<String, Object> outFields = new HashMap<>();
String outputFieldCode = outputJson.getString("field_code");
outFields.put("fieldId", outputJson.getIntValue("field_id"));
outFields.put("fieldName", outputJson.getString("field_name"));
outFields.put("fieldCode", outputFieldCode);
outFields.put("outValue", dicisionResult);
outMap.put("result", dicisionResult);
String key = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_result";
inputParam.put(key, dicisionResult);
inputParam.put(outputFieldCode, dicisionResult);
JSONObject json = new JSONObject();
json.put("nodeId", engineNode.getNodeId());
json.put("nodeName", engineNode.getNodeName());
json.put("outFields", JSONObject.parseObject(JSON.toJSONString(outFields)));
//监控中心===》hbase中写入结果信息
outMap.put("nodeResult",json);
if (outMap.containsKey("decisionJson")) {
JSONArray resultJson = (JSONArray) outMap.get("decisionJson");
resultJson.add(json);
} else {
JSONArray resultJson = new JSONArray();
resultJson.add(json);
outMap.put("decisionJson", resultJson);
}
}
}

View File

@@ -0,0 +1,385 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.model.enginex.risk.InputParam;
import com.fibo.ddp.common.model.enginex.risk.Result;
import com.fibo.ddp.common.model.enginex.runner.ExpressionParam;
import com.fibo.ddp.common.model.strategyx.decisiontable.DecisionTablesDetailCondition;
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesDetailVo;
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesResultVo;
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesVersionVo;
import com.fibo.ddp.common.model.strategyx.decisiontable.vo.DecisionTablesVo;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
import com.fibo.ddp.common.service.redis.RedisManager;
import com.fibo.ddp.common.service.strategyx.decisiontable.DecisionTablesDetailService;
import com.fibo.ddp.common.service.strategyx.decisiontable.DecisionTablesService;
import com.fibo.ddp.common.service.strategyx.decisiontable.impl.DecisionTablesServiceImpl;
import com.fibo.ddp.common.utils.common.MD5;
import com.fibo.ddp.common.utils.constant.CommonConst;
import com.fibo.ddp.enginex.runner.ksession.KSessionPool;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.apache.commons.lang3.StringUtils;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@Service
public class DecisionTablesNode implements EngineRunnerNode {
private static final Logger logger = LoggerFactory.getLogger(DecisionTablesServiceImpl.class);
@Resource
private RedisManager redisManager;
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
private KSessionPool kSessionPool;
@Resource
private DecisionTablesService decisionTablesService;
@Autowired
private DecisionTablesDetailService detailService;
@Autowired
private CommonService commonService;
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
return ExecuteUtils.getExecuteIdList(engineNode, "versionId");
}
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
try {
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
//获取决策表节点的字段id
List<Long> ids = new ArrayList<>();
for (Long versionId : versionIdList) {
ids.addAll(detailService.queryFieldIdByDecisionTablesVersionId(versionId));
}
commonService.getFieldByIds(ids, inputParam);
} catch (Exception e) {
logger.error("【DecisionTablesNode】,getNodeField:获取决策表指标异常");
}
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
//监控中心-节点信息快照记录
if (engineNode != null && engineNode.getNodeJson() != null) {
outMap.put("nodeSnapshot", engineNode.getNodeJson());
}
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode", engineNode);
nodeInfo.put("nodeId", engineNode.getNodeId());
nodeInfo.put("nodeName", engineNode.getNodeName());
nodeInfo.put("nodeType", engineNode.getNodeType());
outMap.put("nodeInfo", nodeInfo);
JSONArray strategySnapshot = new JSONArray();
for (Long versionId : versionIdList) {
//获取决策表decisionTablesVo
DecisionTablesVo decisionTablesVo = decisionTablesService.queryByVersionId(versionId);
//监控中心==策略层面快照信息记录
if (decisionTablesVo.getExecuteVersion().getSnapshot() != null) {
strategySnapshot.add(decisionTablesVo.getExecuteVersion().getSnapshot());
}
DecisionTablesVersionVo version = decisionTablesVo.getExecuteVersion();
//获取存放决策表执行结果的变量
String resultFieldEn = version.getResultFieldEn();
//执行决策表
Object executeResult = this.executeDecisionTables(version, inputParam);
//处理结果
JSONObject jsonObject = new JSONObject();
jsonObject.put("nodeId", engineNode.getNodeId());
jsonObject.put("nodeName", engineNode.getNodeName());
jsonObject.put("decisionTablesId", decisionTablesVo.getId());
jsonObject.put("decisionTablesName", decisionTablesVo.getName());
jsonObject.put("desc", version.getDescription());
jsonObject.put("versionId", version.getId());
jsonObject.put("versionCode", version.getVersionCode());
if (executeResult != null) {
jsonObject.put("result", executeResult);
JSONObject resultField = new JSONObject();
resultField.put(resultFieldEn, executeResult);
//将执行结果按照固定格式存入参数map以供后续节点使用.
// inputParam.put("decisionTable_"+decisionTablesId+"_"+engineNode.getNodeId(),executeResult);
inputParam.put(resultFieldEn, executeResult);
List<JSONObject> fieldList = new ArrayList<>();
fieldList.add(resultField);
//处理自定义输出
List<JSONObject> jsonObjects = decisionTablesService.setOutput(versionId, inputParam);
fieldList.addAll(jsonObjects);
jsonObject.put("fieldList", fieldList);
} else {
jsonObject.put("result", "");
// inputParam.put("decisionTable_"+decisionTablesId+"_"+engineNode.getNodeId(),"");
inputParam.put(resultFieldEn, "");
}
//将执行结果存入最终返回值
if (outMap.containsKey("decisionTablesJson")) {
JSONArray resultJson = (JSONArray) outMap.get("decisionTablesJson");
resultJson.add(jsonObject);
//监控中心==》将执行结果写入Hbase
JSONObject nodeResult = new JSONObject();
nodeResult.put("result", resultJson);
outMap.put("nodeResult", nodeResult);
} else {
JSONArray resultJson = new JSONArray();
resultJson.add(jsonObject);
outMap.put("decisionTablesJson", resultJson);
//监控中心==》将执行结果写入Hbase
JSONObject nodeResult = new JSONObject();
nodeResult.put("result", resultJson);
outMap.put("nodeResult", nodeResult);
}
terminalCondition(engineNode, inputParam, outMap, executeResult);
}
//监控中心==》策略层面快照信息记录
JSONObject jsonObject = new JSONObject();
jsonObject.put("snapshot", strategySnapshot);
outMap.put("decisionTableStrategy", jsonObject);
}
//执行整个决策表返回决策结果数据
public Object executeDecisionTables(DecisionTablesVersionVo versionVo, Map<String, Object> inputParam) {
Future<Integer> top = null;
Future<Integer> left = null;
//取出行列索引
Integer row = -1;
Integer column = -1;
List<DecisionTablesDetailVo> leftDetailVo = versionVo.getLeftDetailVo();
if (CollectionUtils.isEmpty(leftDetailVo)
|| (leftDetailVo.size() == 1
&& StringUtils.isBlank(leftDetailVo.get(0).getFieldEn())
&& CollectionUtils.isEmpty(leftDetailVo.get(0).getChildren()))) {
row = 0;
} else {
//左侧执行
left = threadPoolTaskExecutor.submit(new Callable<Integer>() {
@Override
public Integer call() {
return executeDecisionTablesDetail(versionVo.getLeftDetailVo(), inputParam);
}
});
}
//右侧执行
List<DecisionTablesDetailVo> topDetailVo = versionVo.getTopDetailVo();
if (CollectionUtils.isEmpty(topDetailVo)
|| (topDetailVo.size() == 1
&& StringUtils.isBlank(topDetailVo.get(0).getFieldEn())
&& CollectionUtils.isEmpty(topDetailVo.get(0).getChildren()))) {
column = 0;
} else {
top = threadPoolTaskExecutor.submit(new Callable<Integer>() {
@Override
public Integer call() {
return executeDecisionTablesDetail(versionVo.getTopDetailVo(), inputParam);
}
});
}
try {
if (row == -1) {
row = left.get();
}
if (column == -1) {
column = top.get();
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//行列值均取到的进行处理
if (row >= 0 && column >= 0) {
//根据行列去结果集中找结果返回
DecisionTablesResultVo resultSet = versionVo.getResultSet();
if (row < resultSet.getRows() && column < resultSet.getColumns()) {
String resultValue = resultSet.getResultValue();
JSONArray array = JSON.parseArray(resultValue);
JSONArray rowArray = JSON.parseArray(JSON.toJSONString(array.get(row)));
return rowArray.get(column);
}
}
return null;
}
//执行决策表的条件获取
public Integer executeDecisionTablesDetail(List<DecisionTablesDetailVo> decisionTablesDetailList, Map<String, Object> paramMap) {
for (DecisionTablesDetailVo decisionTablesDetailVo : decisionTablesDetailList) {
//调用drools执行
// int result = recursionExecuteDecisionTablesDetail(decisionTablesDetailVo, paramMap);
//调用不使用drools执行
int result = executeDecisionTablesDetail(decisionTablesDetailVo, paramMap);
if (result >= 0) {
return result;
}
}
return -1;
}
//执行决策表详情得出位置坐标:drools执行
public int recursionExecuteDecisionTablesDetail(DecisionTablesDetailVo decisionTablesDetailVo, Map<String, Object> paramMap) {
StatefulKnowledgeSession kSession = null;
String keyMd5 = null;
try {
//解析content
String ruleString = decisionTablesDetailVo.getContent().replace("\\r\\n", "\r\n");
ruleString = ruleString.replace("\\t", "\t");
keyMd5 = CommonConst.DROOLS_KSESSION_KEY_PREFIX + MD5.GetMD5Code(ruleString);
redisManager.set(keyMd5, ruleString, 120);
//drools执行
kSession = kSessionPool.borrowObject(keyMd5);
List<Result> resultList = new ArrayList<>();
InputParam inputParam = new InputParam();
inputParam.setInputParam(paramMap);
inputParam.setResult(resultList);
FactHandle fact = kSession.insert(inputParam);
kSession.fireAllRules();
kSession.retract(fact);
//获取执行结果对结果进行分析。
List<Result> results = inputParam.getResult();
Map<String, Object> resultMap = new HashMap<>();
if (results != null && results.size() > 0 && results.get(0) != null && results.get(0).getMap() != null) {
resultMap = inputParam.getResult().get(0).getMap();
}
//本节点命中后处理
if (resultMap.containsKey("result")) {
Integer type = decisionTablesDetailVo.getType();
List<DecisionTablesDetailVo> children = decisionTablesDetailVo.getChildren();
if (type != null) {
switch (type) {
//普通节点符合,让子节点继续执行。
case 1:
if (children != null && children.size() > 0) {
for (DecisionTablesDetailVo child : children) {
int result = this.recursionExecuteDecisionTablesDetail(child, paramMap);
if (result >= 0) {
return result;
}
}
}
break;
//叶子节点符合,返回叶子节点的值。
case 2:
return decisionTablesDetailVo.getIndexValue();
default:
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
logger.error("请求异常", e);
} finally {
if (keyMd5 != null && kSession != null) {
kSessionPool.returnObject(keyMd5, kSession);
}
}
//执行至此则不命中。
return -1;
}
//不使用drools的执行
private int executeDecisionTablesDetail(DecisionTablesDetailVo decisionTablesDetailVo, Map<String, Object> paramMap) {
//获取需要执行的条件列表
List<DecisionTablesDetailCondition> conditionList = decisionTablesDetailVo.getConditionList();
String fieldEn = decisionTablesDetailVo.getFieldEn();
String logical = decisionTablesDetailVo.getLogical();
boolean result = false;
//根据不通关系进行处理
switch (logical) {
case "||":
result = false;
for (DecisionTablesDetailCondition condition : conditionList) {
ExpressionParam expressionParam = new ExpressionParam();
BeanUtils.copyProperties(condition, expressionParam);
expressionParam.setFieldEn(fieldEn);
try {
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
if (expressionResult) {
result = true;
break;
}
}catch (Throwable e){
logger.error("【DecisionTablesNode】runNode执行异常expressionParam{}",expressionParam);
result = false;
break;
}
}
break;
case "&&":
result = true;
for (DecisionTablesDetailCondition condition : conditionList) {
ExpressionParam expressionParam = new ExpressionParam();
BeanUtils.copyProperties(condition, expressionParam);
expressionParam.setFieldEn(fieldEn);
try {
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
if (!expressionResult) {
result = false;
break;
}
}catch (Throwable e){
logger.error("【DecisionTablesNode】runNode执行异常expressionParam{}",expressionParam);
result = false;
break;
}
}
break;
}
//如果本节点符合则执行后续节点
if (result) {
Integer type = decisionTablesDetailVo.getType();
List<DecisionTablesDetailVo> children = decisionTablesDetailVo.getChildren();
if (type != null) {
switch (type) {
//普通节点符合,让子节点继续执行。
case 1:
if (children != null && children.size() > 0) {
for (DecisionTablesDetailVo child : children) {
int executeResult = this.executeDecisionTablesDetail(child, paramMap);
if (executeResult >= 0) {
return executeResult;
}
}
}
break;
//叶子节点符合,返回叶子节点的值。
case 2:
return decisionTablesDetailVo.getIndexValue();
default:
break;
}
}
}
return -1;
}
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, Object executeResult) {
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_result";
Map<String, Object> map = new HashMap<>();
map.put(resultKey, executeResult);
ExecuteUtils.terminalCondition(engineNode, inputParam, outMap, map);
}
}

View File

@@ -0,0 +1,215 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.model.enginex.runner.ExpressionParam;
import com.fibo.ddp.common.model.strategyx.decisiontree.DecisionTreeDetail;
import com.fibo.ddp.common.model.strategyx.decisiontree.DecisionTreeDetailCondition;
import com.fibo.ddp.common.model.strategyx.decisiontree.vo.DecisionTreeVersionVo;
import com.fibo.ddp.common.model.strategyx.decisiontree.vo.DecisionTreeVo;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
import com.fibo.ddp.common.service.strategyx.decisiontree.DecisionTreeService;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class DecisionTreeNode implements EngineRunnerNode {
@Autowired
private DecisionTreeService decisionTreeService;
@Autowired
private CommonService commonService;
private List<Long> getExecuteVersionIdList(EngineNode engineNode){
return ExecuteUtils.getExecuteIdList(engineNode,"versionId");
}
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
List<Long> list = getExecuteVersionIdList(engineNode);
List<Long> fieldIds = new ArrayList<>();
for (Long l : list) {
fieldIds.addAll(decisionTreeService.getNodeFieldIds(l));
}
commonService.getFieldByIds(fieldIds,inputParam);
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
//监控中心--记录节点快照信息
if (engineNode != null && engineNode.getSnapshot() != null) {
outMap.put("nodeSnapshot", engineNode.getSnapshot());
}
List<Long> list = getExecuteVersionIdList(engineNode);
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode", engineNode);
nodeInfo.put("nodeId", engineNode.getNodeId());
nodeInfo.put("nodeName", engineNode.getNodeName());
nodeInfo.put("nodeType", engineNode.getNodeType());
outMap.put("nodeInfo", nodeInfo);
JSONArray strategySnapshot = new JSONArray();
for (Long versionId : list) {
DecisionTreeVo decisionTreeVo = decisionTreeService.queryExecuteDecisionTree(null, versionId);
if (decisionTreeVo == null) {
continue;
}
//监控中心==策略层面快照信息记录
if(decisionTreeVo.getExecuteVersion().getSnapshot()!=null){
strategySnapshot.add(decisionTreeVo.getExecuteVersion().getSnapshot());
}
DecisionTreeVersionVo version = decisionTreeVo.getExecuteVersion();
String resultFieldEn = version.getResultFieldEn();
//执行决策表
Object executeResult = this.executeDecisionTree(version, inputParam);
//处理结果
JSONObject jsonObject = new JSONObject();
jsonObject.put("nodeId", engineNode.getNodeId());
jsonObject.put("nodeName", engineNode.getNodeName());
jsonObject.put("decisionTreeId", decisionTreeVo.getId());
jsonObject.put("decisionTreeName", decisionTreeVo.getName());
jsonObject.put("desc", version.getDescription());
jsonObject.put("versionId", version.getId());
jsonObject.put("versionCode", version.getVersionCode());
if (executeResult != null) {
jsonObject.put("result", executeResult);
JSONObject resultField = new JSONObject();
resultField.put(resultFieldEn, executeResult);
inputParam.put(resultFieldEn, executeResult);
List<JSONObject> fieldList = new ArrayList<>();
fieldList.add(resultField);
//处理自定义输出
List<JSONObject> jsonObjects = decisionTreeService.setOutput(versionId, inputParam);
fieldList.addAll(jsonObjects);
jsonObject.put("fieldList", fieldList);
} else {
jsonObject.put("result", "");
inputParam.put(resultFieldEn, "");
}
//将执行结果存入最终返回值
if (outMap.containsKey("decisionTreeJson")) {
JSONArray resultJson = (JSONArray) outMap.get("decisionTreeJson");
resultJson.add(jsonObject);
//监控中心==》将执行结果写入Hbase
JSONObject nodeResult = new JSONObject();
nodeResult.put("result", resultJson);
outMap.put("nodeResult", nodeResult);
} else {
JSONArray resultJson = new JSONArray();
resultJson.add(jsonObject);
outMap.put("decisionTreeJson", resultJson);
//监控中心==》将执行结果写入Hbase
JSONObject nodeResult = new JSONObject();
nodeResult.put("result", resultJson);
outMap.put("nodeResult", nodeResult);
}
terminalCondition(engineNode,inputParam,outMap,executeResult);
}
//监控中心==》策略层面快照信息记录
JSONObject jsonObject = new JSONObject();
jsonObject.put("snapshot",strategySnapshot);
outMap.put("decisionTreeStrategy",jsonObject);
}
private Object executeDecisionTree(DecisionTreeVersionVo version, Map<String, Object> inputParam) {
List<DecisionTreeDetail> detailList = version.getDetailList();
for (DecisionTreeDetail decisionTreeDetail : detailList) {
Object o = executeDecisionTreeDetail(decisionTreeDetail, inputParam);
if (o != null) {
return o;
}
}
return null;
}
private Object executeDecisionTreeDetail(DecisionTreeDetail detail, Map<String, Object> paramMap) {
//获取需要执行的条件列表
List<DecisionTreeDetailCondition> conditionList = detail.getConditionList();
String fieldEn = detail.getFieldEn();
String logical = detail.getLogical();
boolean result = false;
//根据不通关系进行处理
switch (logical) {
case "||":
result = false;
for (DecisionTreeDetailCondition condition : conditionList) {
ExpressionParam expressionParam = new ExpressionParam();
BeanUtils.copyProperties(condition, expressionParam);
expressionParam.setFieldEn(fieldEn);
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
if (expressionResult) {
result = true;
break;
}
}
break;
case "&&":
result = true;
for (DecisionTreeDetailCondition condition : conditionList) {
ExpressionParam expressionParam = new ExpressionParam();
BeanUtils.copyProperties(condition, expressionParam);
expressionParam.setFieldEn(fieldEn);
boolean expressionResult = ExecuteUtils.getExpressionResult(expressionParam, paramMap);
if (!expressionResult) {
result = false;
break;
}
}
break;
}
//如果本节点符合则执行后续节点
if (result) {
Integer type = detail.getNodeType();
List<DecisionTreeDetail> children = detail.getChildren();
if (type == null) {
if (children == null || children.isEmpty()) {
type = 2;
} else {
type = 1;
}
}
if (type != null) {
switch (type) {
//普通节点符合,让子节点继续执行。
case 1:
if (children != null && children.size() > 0) {
for (DecisionTreeDetail child : children) {
Object executeResult = this.executeDecisionTreeDetail(child, paramMap);
if (executeResult != null) {
return executeResult;
}
}
}
break;
//叶子节点符合,返回叶子节点的值。
case 2:
String resultStr = detail.getResultValue();
Object resultValue = resultStr;
Integer variableType = detail.getVariableType();
if (variableType == 2) {
resultValue = ExecuteUtils.getObjFromMap(paramMap, resultStr);
} else if (variableType == 3) {
resultValue = ExecuteUtils.getObjFromScript(paramMap, resultStr);
}
return resultValue;
default:
break;
}
}
}
return null;
}
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap,Object executeResult) {
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_result";
Map<String,Object> map = new HashMap<>();
map.put(resultKey,executeResult);
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap, map);
}
}

View File

@@ -0,0 +1,107 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.utils.constant.CommonConst;
import com.fibo.ddp.common.utils.util.runner.JevalUtil;
import com.fibo.ddp.common.utils.util.runner.jeval.EvaluationException;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class GroupNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CommonService commonService;
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
logger.info("start【获取分组节点指标】GroupNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
JSONObject jsonObject = JSONObject.parseObject(engineNode.getNodeScript());
JSONArray array = jsonObject.getJSONArray("fields");
List<Long> ids = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
JSONObject input = array.getJSONObject(i);
Object fieldId = input.get("fieldId");
if(fieldId != null && !"".equals(fieldId.toString())){
ids.add(Long.valueOf(fieldId.toString()));
}
}
commonService.getFieldByIds(ids, inputParam);
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
JSONObject jsonScript = JSONObject.parseObject(engineNode.getNodeScript());
//监控中心--节点信息记录(不需要策略层面的监控)
outMap.put("nodeSnapshot",JSONObject.parse(engineNode.getNodeJson()));
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode",engineNode);
nodeInfo.put("nodeId",engineNode.getNodeId());
nodeInfo.put("nodeName",engineNode.getNodeName());
nodeInfo.put("nodeType",engineNode.getNodeType());
outMap.put("nodeInfo",nodeInfo);
try {
String nextNode = handleClassify(jsonScript, inputParam);
outMap.put("nextNode", nextNode);
JSONObject result = new JSONObject();
result.put("nodeResult",nextNode);
outMap.put("nodeResult",result);
} catch (EvaluationException e) {
e.printStackTrace();
logger.error("请求异常", e);
}
}
private static String handleClassify(JSONObject jsonScript, Map<String, Object> inputParam) throws EvaluationException {
JSONArray conditions = jsonScript.getJSONArray("conditions");
JSONArray fields = jsonScript.getJSONArray("fields");
Map<String, Object> variablesMap = new HashMap<>();
variablesMap.putAll(inputParam);
Map<String, Integer> fieldsMap = new HashMap<>();
for(int i = 0; i < fields.size(); i++){
JSONObject jsonObject = fields.getJSONObject(i);
fieldsMap.put(jsonObject.getString("fieldCode"), jsonObject.getIntValue("valueType"));
}
JevalUtil.convertVariables(fieldsMap, variablesMap);
String nextNode = "";
if (conditions == null || conditions.isEmpty()) {
//TODO 如果为空,如何处理
return nextNode;
} else {
int size = conditions.size();
boolean flag = false;
JSONObject formula = null;
for (int i = 0; i < size; i++) {
formula = conditions.getJSONObject(i);
//公式为空则为else条件分支
if (CommonConst.STRING_EMPTY.equals(formula.getString("formula"))) {
//else条件
if (nextNode.equals(CommonConst.STRING_EMPTY)) {
nextNode = formula.getString("nextNode");
}
} else {
//正常条件分支
flag = JevalUtil.evaluateBoolean(formula.getString("formula"), variablesMap);
if (flag) {
nextNode = formula.getString("nextNode");
break;
}
}
}
return nextNode;
}
}
}

View File

@@ -0,0 +1,284 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
import com.fibo.ddp.common.service.strategyx.listlibrary.ListDbService;
import com.fibo.ddp.common.utils.constant.enginex.NodeTypeEnum;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListDbNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CommonService commonService;
@Resource
private ListDbService listDbService;
private List<Long> getExecuteVersionIdList(EngineNode engineNode){
return ExecuteUtils.getExecuteIdList(engineNode,"versionId");
}
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
List<Long> list = getExecuteVersionIdList(engineNode);
List<Long> fieldIds = new ArrayList<>();
for (Long l : list) {
fieldIds.addAll(listDbService.getNodeFieldIds(l));
}
commonService.getFieldByIds(fieldIds,inputParam);
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
//监控中心--节点信息快照记录,主要用于监控中心节点信息配置页面显示
JSONObject snapshot = new JSONObject();
snapshot.put("snapshot",engineNode.getSnapshot());
outMap.put("nodeSnapshot",snapshot);
inputParam.put("nodeId", engineNode.getNodeId());
inputParam.put("nodeName", engineNode.getNodeName());
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode",engineNode);
nodeInfo.put("nodeId",engineNode.getNodeId());
nodeInfo.put("nodeName",engineNode.getNodeName());
nodeInfo.put("nodeType",engineNode.getNodeType());
outMap.put("nodeInfo",nodeInfo);
int type = 0;
if(engineNode.getNodeType() == NodeTypeEnum.BLACKLIST.getValue()){
type = 1;
} else if(engineNode.getNodeType() == NodeTypeEnum.WHITELIST.getValue()){
type = 2;
}
boolean isfalg = this.findByQueryKey(inputParam, outMap, type,engineNode);
if (isfalg) {
if (type == 1) {
outMap.put("isBlack", "true");
outMap.put("enginefalg", "true");
// engineNode.setNextNodes(null);
} else {
outMap.put("isWhite", "true");
outMap.put("engineWhite", "true");
// engineNode.setNextNodes(null);
}
}
}
/**
* 根据传入数据监测是否命中黑名单
*
* @param paramMap
* @return
* @see
*/
public boolean findByQueryKey(Map<String, Object> paramMap, Map<String, Object> outmap, Integer type,EngineNode engineNode) {
// SessionData sessionData = SessionManager.getSession();
// Long organId = sessionData.getOrganId();
// JSONObject blackandWhite = new JSONObject();
// JSONObject resultJson = new JSONObject();
// //传递nodeId
// String strlistDbIds = null;
// if (!paramMap.get("nodeId").equals("0")) {
// NodeListDb nodeListDb = nodeListDbMapper.findByNodeId(paramMap);
// strlistDbIds = nodeListDb.getInnerListdbs();
// //节点配置信息快照hbase入库用
//// JSONObject bwNodeSnopshot = new JSONObject();
//// String strListDbIdsOut = nodeListDb.getOuterListdbs();
//// if(strListDbIdsOut!=null && strListDbIdsOut.length()>0){
//// bwNodeSnopshot.put("outerIdList",strListDbIdsOut.split(","));
//// }
// //循环处理所有内部黑/白名单库
// String[] arraylistDBIds = null;
// Integer matchs = 0;
// Integer revMatchs = 0; //模糊查询时反向匹配
// if (strlistDbIds.length() > 0) {
// arraylistDBIds = strlistDbIds.split(",");
//// bwNodeSnopshot.put("innerIdList",arraylistDBIds);
//// outmap.put("nodeSnapshot",bwNodeSnopshot);
// String hitKey = ""+engineNode.getNodeType()+"_"+engineNode.getNodeId()+"_size";
// int hitSize = 0;
// JSONArray strategySnopshot = new JSONArray();
// for (int i = 0; i < arraylistDBIds.length; i++) {
// HashMap<String, Object> param1 = new HashMap<String, Object>();
// param1.put("organId", organId);
// Integer listDbId = Integer.valueOf(arraylistDBIds[i]).intValue();
// param1.put("listDbId", listDbId);
// ListDb listDb = new ListDb();
//// listDb = listDbService.findListDbByIdandByorganId(param1);
// //监控中心--策略层面记录名单库快照信息
// if(listDb.getSnapshot()!=null){
// strategySnopshot.add(listDb.getSnapshot());
// }
// paramMap.put("listDb", listDb);
// String listType = listDb.getListType();
// String queryKeyArray[] = listDb.getQueryField().split(",");
// if (queryKeyArray.length > 0) {
// Integer queryType = listDb.getQueryType();//and1or0
// Integer matchType = listDb.getMatchType();//精确匹配1模糊匹配0
//
// String queryKey = ""; // t1 like '%t1%'
// String revQueryKey = ""; // 反向模糊匹配 instr('高档洗浴消费',t1) t1行业字段 eg.'洗浴'
// String tableName = "organ" + "_" + organId + "_" + listType + "_" + listDbId;
// paramMap.put("tableName", tableName);
// paramMap.put("schemaName", getDbName());
//
// //获取名单库的匿名字段与注释的关系
// List<TblColumn> columnList = tblColumnMapper.getColumnList(paramMap);
//
// //字段id转匿名字段名准备待查字段条件
// Integer loc = 0;
//
// for (int j = 0; j < queryKeyArray.length; j++) {
//
// HashMap<String, Object> inputParam = new HashMap<String, Object>();
// inputParam.put("id", queryKeyArray[j]);
// inputParam.put("organId", organId);
// inputParam.put("engineId", null);
// //id(3)-field(age)
// Field field = fieldMapper.findByFieldIdbyorganId(inputParam);
// String fieldEn = field.getFieldEn(); //age
//
// for (TblColumn tblColumn : columnList) {
//
// String colComment = tblColumn.getColComment(); //age
// String colName = tblColumn.getColName(); //t5
// String paramValue =paramMap.get(fieldEn).toString();
//
// if (colName.startsWith("t") && queryKeyArray[j].equals(colComment)) {
//
// if (paramValue == null || paramValue.equals("")) {
// return false; //数据项缺失导致无法命中,默认返回没命中
// } else {
// loc += 1;
// if (matchType == 1) {
// if (loc > 1 && queryType == 1) {
// queryKey += " and ";
// } else if (loc > 1 && queryType == 0) {
// queryKey += " or ";
// }
// queryKey += colName + " = '" + paramValue + "'";
// } else if (matchType == 0) { //模糊匹配
// if (loc > 1 && queryType == 1) {
// queryKey += " and ";
// } else if (loc > 1 && queryType == 0) {
// queryKey += " or ";
// revQueryKey += " + ";
// }
// //正向模糊搜索
// queryKey += colName + " like " + "'%" + paramValue + "%'"; // t5 like '%36岁%'
// //反向模糊搜索
// revQueryKey += "max(instr('" + paramValue + "'," + colName + "))";
// }
// }
// }
// }
// }
// paramMap.put("queryKey", queryKey);
// paramMap.put("revQueryKey", revQueryKey);
// }
// matchs += custListMapper.findByQueryKey(paramMap);
// if (!paramMap.get("revQueryKey").equals("")) {
// revMatchs = custListMapper.revFindByQueryKey(paramMap);
// }
// if (revMatchs == null)
// revMatchs = 0;
//
// paramMap.put(listDb.getResultFieldEn(),"未命中");
// List<JSONObject> fieldList = new ArrayList<>();
//
// JSONObject hitResult = new JSONObject();
// hitResult.put(listDb.getResultFieldEn(),"未命中");
// if (matchs + revMatchs > 0) {
// resultJson.put("nodeId", paramMap.get("nodeId").toString());
// resultJson.put("nodeName", paramMap.get("nodeName").toString());
// resultJson.put("status", "0x0000");
// paramMap.put(listDb.getResultFieldEn(),"命中");
// hitResult.put(listDb.getResultFieldEn(),"命中");
// hitSize++;
// List<JSONObject> jsonObjects = outputService.setOutput(new StrategyOutput(Long.valueOf(listDbId.toString()), StrategyType.LIST_DB), paramMap);
// fieldList.add(hitResult);
// fieldList.addAll(jsonObjects);
// resultJson.put("fieldList",fieldList);
// if (type == 1) {
// blackandWhite.put("resultType", 5);
// outmap.put("black", listDb);
// resultJson.put("blackId", listDb.getId());
// resultJson.put("blackName", listDb.getListName());
// resultJson.put("blackType", listDb.getListType());
// if (null != listDb.getListDesc()) {
// resultJson.put("desc", listDb.getListDesc());
// }
//
// blackandWhite.put("resultJson", resultJson);
// //黑名单api返回
// outmap.put("blackJson", blackandWhite);
// } else {
// blackandWhite.put("resultType", 6);
// resultJson.put("status", "0x0000");
// resultJson.put("whiteId", listDb.getId());
// resultJson.put("whiteName", listDb.getListName());
// resultJson.put("whiteType", listDb.getListType());
// if (null != listDb.getListDesc()) {
// resultJson.put("desc", listDb.getListDesc());
// }
// blackandWhite.put("resultJson", resultJson);
// //白名单api返回
// outmap.put("whiteJson", blackandWhite);
// outmap.put("white", listDb);
// }
// paramMap.put(hitKey,hitSize);
// return true;
// }else {
// //未命中
// blackandWhite.put("resultJson","未命中");
// fieldList.add( hitResult);
// }
// //监控中心==》将评分卡的执行结果得分明细放入 输出变量池 用于存入hbase
// outmap.put("nodeResult",blackandWhite);
// }
// paramMap.put(hitKey,hitSize);
// //监控中心==》策略层面记录策略的快照信息
// JSONObject strategyObject = new JSONObject();
// strategyObject.put("strategySnopshot",strategySnopshot);
// outmap.put("strategySnopshot",strategyObject);
// } else
// return false;
// }
return false;
}
/**
* Description: 获取jdbc.properties里配置的数据库名
*
* @return
* @see
*/
private String getDbName() {
// ResourceBundle resource = ResourceBundle.getBundle("conf/jdbc");
// String mysqlUrl = resource.getString("mysql.url");
//
// String aArray[] = mysqlUrl.split("/");
// String bArray[] = aArray[3].split("\\?");
// String dbName = bArray[0];
//
// return dbName;
return "riskmanage";
}
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap,Object executeResult) {
String sizeKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_size";
Map<String,Object> map = new HashMap<>();
map.put(sizeKey,executeResult);
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap, map);
}
}

View File

@@ -0,0 +1,128 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.model.strategyx.aimodel.MachineLearningModels;
import com.fibo.ddp.common.model.strategyx.strategyout.StrategyOutput;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
import com.fibo.ddp.common.service.strategyx.aimodel.ModelsService;
import com.fibo.ddp.common.service.strategyx.aimodel.PMMLExecutor.PMMLExecutor;
import com.fibo.ddp.common.service.strategyx.strategyout.StrategyOutputService;
import com.fibo.ddp.common.utils.constant.strategyx.StrategyType;
import com.fibo.ddp.common.utils.util.StringUtil;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class ModelNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CommonService commonService;
@Resource
public ModelsService modelsService;
@Resource(name = "PMMLExecutorRFImpl")
private PMMLExecutor pmmlExecutor;
@Resource
private StrategyOutputService outputService;
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
return ExecuteUtils.getExecuteIdList(engineNode, "modelId");
}
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
logger.info("start【获取模型节点指标】ModelNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
// Long modelId = Long.valueOf(engineNode.getNodeJson());
List<Long> modelIds = getExecuteVersionIdList(engineNode);
List<Long> ids = new ArrayList<>();
for (Long modelId : modelIds) {
MachineLearningModels models = modelsService.selectById(Integer.valueOf(modelId.toString()));
ids.addAll(StringUtil.toLongList(models.getMappingField()));
}
try {
commonService.getFieldByIds(ids, inputParam);
}catch (Exception e){
logger.error("模型中字段未完全找到");
e.printStackTrace();
}
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
List<Long> modelIds = getExecuteVersionIdList(engineNode);
if (modelIds == null || modelIds.isEmpty()){
logger.error("模型节点内容为空node{}",engineNode);
return;
}
Long modelId = modelIds.get(0);
MachineLearningModels models = modelsService.selectById(Integer.valueOf(modelId.toString()));
//监控中心--节点信息记录
outMap.put("nodeSnapshot", models);
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode", engineNode);
nodeInfo.put("nodeId", engineNode.getNodeId());
nodeInfo.put("nodeName", engineNode.getNodeName());
nodeInfo.put("nodeType", engineNode.getNodeType());
outMap.put("nodeInfo", nodeInfo);
// 加载模型文件
org.jpmml.evaluator.Evaluator evaluator = pmmlExecutor.loadPmml(models.getFilePath());
Map<String, Object> input = new HashMap<>();
String[] modelFieldArr = models.getModelField().split(",");
String[] mappingFieldArr = models.getMappingField().split(",");
for (int i = 0; i < modelFieldArr.length; i++) {
input.put(modelFieldArr[i], inputParam.get(mappingFieldArr[i]));
}
// 调用模型
double modelResult = 0d;
try {
modelResult =pmmlExecutor.predict(evaluator, input);
}catch (Exception e){
logger.error("模型节点执行异常,node{}",engineNode);
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("nodeId", engineNode.getNodeId());
jsonObject.put("nodeName", engineNode.getNodeName());
jsonObject.put("modelId", models.getId());
jsonObject.put("modelName", models.getModelName());
List<JSONObject> fieldList = new ArrayList<>();
JSONObject result = new JSONObject();
result.put(models.getResultFieldEn(), modelResult);
fieldList.add(result);
fieldList.addAll(outputService.setOutput(new StrategyOutput(modelId, StrategyType.MODELS), input));
jsonObject.put("fieldList", fieldList);
outMap.put("nodeResult", jsonObject);
if (outMap.containsKey("modelJson")) {
JSONArray resultJson = (JSONArray) outMap.get("modelJson");
resultJson.add(jsonObject);
} else {
JSONArray resultJson = new JSONArray();
resultJson.add(jsonObject);
outMap.put("modelJson", resultJson);
}
inputParam.put("model_" + modelId, modelResult);
inputParam.put(models.getResultFieldEn(), modelResult);
outMap.put("model_" + modelId, modelResult);
terminalCondition(engineNode, inputParam, outMap, modelResult);
}
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, Object executeResult) {
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_result";
Map<String, Object> map = new HashMap<>();
map.put(resultKey, executeResult);
ExecuteUtils.terminalCondition(engineNode, inputParam, outMap, map);
}
}

View File

@@ -0,0 +1,33 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 并行节点
*/
@Service
public class ParallelNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
logger.info("start【执行并行节点】ParallelNode.runNode engineNode:{},inputParam:{},outMap:{}"
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
if (engineNode != null && engineNode.getSnapshot() != null) {
outMap.put("nodeSnapshot", engineNode.getSnapshot());
}
}
}

View File

@@ -0,0 +1,59 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.datax.datainterface.InterfaceInfo;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.service.datax.datainterface.InterfaceService;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 远程调用节点
*/
@Service
public class RpcNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private InterfaceService interfaceService;
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
logger.info("start【执行RPC节点】RpcNode.runNode engineNode:{},inputParam:{},outMap:{}"
, JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam), JSONObject.toJSONString(outMap));
if (engineNode != null && engineNode.getSnapshot() != null) {
outMap.put("nodeSnapshot", engineNode.getSnapshot());
}
JSONObject nodeJson = JSONObject.parseObject(engineNode.getNodeJson());
JSONObject callConfig = nodeJson.getJSONObject("callConfig");
int callType = callConfig.getInteger("callType");
JSONArray resultConfig = nodeJson.getJSONArray("resultConfig");
InterfaceInfo interfaceInfo = interfaceService.getInterfaceById(callConfig.getInteger("interfaceId"));
// 发送http请求
String result = interfaceService.getHttpResponse(interfaceInfo, inputParam, callType);
// 解析指标
parseField(result, resultConfig, inputParam);
}
private void parseField(String result, JSONArray resultConfig, Map<String, Object> inputParam){
if(resultConfig != null && !resultConfig.isEmpty() && StringUtils.isNotBlank(result)){
JSONObject configJson = resultConfig.getJSONObject(0);
String fieldEn = configJson.getString("fieldEn");
String parseField = configJson.getString("parseField");
String fieldValue = interfaceService.interfaceParseField(parseField, result);
inputParam.put(fieldEn, fieldValue);
}
}
}

View File

@@ -0,0 +1,769 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.datax.datamanage.Field;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.model.enginex.runner.ExpressionParam;
import com.fibo.ddp.common.model.strategyx.guiderule.RuleInfo;
import com.fibo.ddp.common.model.strategyx.guiderule.RuleLoopGroupAction;
import com.fibo.ddp.common.model.strategyx.guiderule.vo.RuleConditionVo;
import com.fibo.ddp.common.model.strategyx.guiderule.vo.RuleVersionVo;
import com.fibo.ddp.common.model.strategyx.scriptrule.RuleScriptVersion;
import com.fibo.ddp.common.service.datax.datamanage.FieldService;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
import com.fibo.ddp.common.service.strategyx.guiderule.RuleConditionService;
import com.fibo.ddp.common.service.strategyx.guiderule.RuleService;
import com.fibo.ddp.common.service.strategyx.guiderule.RuleVersionService;
import com.fibo.ddp.common.service.strategyx.scriptrule.RuleScriptVersionService;
import com.fibo.ddp.common.utils.constant.Constants;
import com.fibo.ddp.common.utils.constant.strategyx.RuleConst;
import com.fibo.ddp.common.utils.constant.strategyx.StrategyType;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
@Service
public class RuleSetNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CommonService commonService;
@Resource
private RuleService ruleService;
@Autowired
private RuleConditionService conditionService;
@Resource
private RuleScriptVersionService ruleScriptVersionService;
@Resource
private FieldService fieldService;
@Autowired
private RuleVersionService versionService;
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
logger.info("start【获取规则集节点指标】RuleSetNode.getNodeField engineNode:{},inputParam:{}", JSONObject.toJSONString(engineNode), JSONObject.toJSONString(inputParam));
JSONObject nodeJson = JSONObject.parseObject(engineNode.getNodeJson());
List<Long> ids = new ArrayList<>();
List<Long> versionIds = new ArrayList<>(); // 复杂规则集
List<Long> scriptVersionIds = new ArrayList<>(); // 脚本规则集
JSONArray jsonArray = null;
int groupType = nodeJson.getInteger("groupType");
if (groupType == Constants.ruleNode.MUTEXGROUP) {
jsonArray = nodeJson.getJSONObject("mutexGroup").getJSONArray("rules");
} else {
jsonArray = nodeJson.getJSONObject("executeGroup").getJSONArray("rules");
}
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject ruleObj = jsonArray.getJSONObject(i);
Long versionId = ruleObj.getLong("ruleVersionId");
Long difficulty = ruleObj.getLong("difficulty");
if (difficulty != null && difficulty == 3) {
scriptVersionIds.add(versionId); // 脚本式规则
} else if (versionId != null) {
versionIds.add(versionId); // 复杂规则
}
}
//获取字段en
List<String> fieldEnList = new ArrayList<>();
if (!versionIds.isEmpty()) {
fieldEnList.addAll(conditionService.queryFieldEnByVersionIds(versionIds));
}
if (!scriptVersionIds.isEmpty()) {
fieldEnList.addAll(ruleScriptVersionService.queryFieldEnByVersionIds(scriptVersionIds));
}
//筛选调那些循环或者嵌套中的字段
fieldEnList = fieldEnList.stream().distinct().filter(f -> f != null && !f.contains(".") && !f.contains("%")).collect(Collectors.toList());
if (fieldEnList != null && !fieldEnList.isEmpty()) {
List<Field> fieldList = fieldService.selectFieldListByEns(fieldEnList);
for (Field field : fieldList) {
ids.add(field.getId());
}
}
if (!ids.isEmpty()) {
commonService.getFieldByIds(ids, inputParam);
}
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
JSONObject nodeJson = JSONObject.parseObject(engineNode.getNodeJson());
//监控中心--记录节点快照信息
if (engineNode != null && engineNode.getSnapshot() != null) {
outMap.put("nodeSnapshot", engineNode.getSnapshot());
}
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode", engineNode);
nodeInfo.put("nodeId", engineNode.getNodeId());
nodeInfo.put("nodeName", engineNode.getNodeName());
nodeInfo.put("nodeType", engineNode.getNodeType());
outMap.put("nodeInfo", nodeInfo);
int groupType = nodeJson.getInteger("groupType") == null ? Constants.ruleNode.EXECUTEGROUP : nodeJson.getInteger("groupType");
CopyOnWriteArrayList<Map> ruleResultList = new CopyOnWriteArrayList<>();// 规则执行结果集合
List<RuleInfo> ruleHitList = new ArrayList<>(); // 命中的规则集合
// 互斥组(串行)
if (groupType == Constants.ruleNode.MUTEXGROUP) {
JSONArray jsonArray = nodeJson.getJSONObject("mutexGroup").getJSONArray("rules");
List<RuleInfo> ruleInfoList = getRuleFromJsonArray(jsonArray);
//监控中心--循环获取策略层面的快照信息
recordStrategySnopshot(ruleInfoList, outMap);
ruleHitList = serialRule(inputParam, outMap, ruleInfoList, ruleResultList);
}
// 执行组(并行)
else if (groupType == Constants.ruleNode.EXECUTEGROUP) {
JSONArray jsonArray = nodeJson.getJSONObject("executeGroup").getJSONArray("rules");
List<RuleInfo> ruleInfoList = getRuleFromJsonArray(jsonArray);
//监控中心--循环获取策略层面的快照信息
recordStrategySnopshot(ruleInfoList, outMap);
ruleHitList = parallelRule(inputParam, outMap, ruleInfoList, ruleResultList);
}
// 终止条件处理
terminalCondition(engineNode, nodeJson, outMap, ruleHitList);
JSONObject jsonObject = new JSONObject();
jsonObject.put("nodeId", engineNode.getNodeId());
jsonObject.put("nodeName", engineNode.getNodeName());
jsonObject.put("ruleResultList", ruleResultList);
if (outMap.containsKey("ruleJson")) {
JSONArray resultJson = (JSONArray) outMap.get("ruleJson");
resultJson.add(jsonObject);
} else {
JSONArray resultJson = new JSONArray();
resultJson.add(jsonObject);
outMap.put("ruleJson", resultJson);
}
int hitSize = 0;
double scoreSum = 0d;
for (Map map : ruleResultList) {
Object ruleScore = map.get("ruleScore");
Object ruleResult = map.get("ruleResult");
if (null != ruleResult && "命中".equals(ruleResult)) {
hitSize++;
if (null != ruleScore) {
try {
scoreSum += Double.valueOf(ruleScore.toString());
} catch (Exception e) {
continue;
}
}
}
}
String hitKey = "" + engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_size";
String scoreKey = "" + engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_score";
inputParam.put(hitKey, hitSize);
inputParam.put(scoreKey, scoreSum);
//监控中心==》记录节点输出结果
//记录整个规则集中的所有规则的命中情况,以及总的统计次数 放到输出变量池
JSONObject nodeResult = new JSONObject();
nodeResult.put("ruleResultList", ruleResultList);
nodeResult.put("hitNum", hitSize);
nodeResult.put("scoreTotal", scoreSum);
outMap.put("nodeResult", nodeResult);
}
/**
* 监控中心--获取策略层面快照信息
*
* @param ruleInfoList
* @param outMap
*/
private void recordStrategySnopshot(List<RuleInfo> ruleInfoList, Map<String, Object> outMap) {
JSONArray jsonObject = new JSONArray();
ruleInfoList.stream().forEach(ruleInfo -> {
logger.info("===========================监控添加策略信息快照情况==============版本id:{}=====:{}",ruleInfo.getVersion().getId(),ruleInfo.getVersion().getSnapshot());
if (ruleInfo.getVersion().getSnapshot() != null) {
jsonObject.add(ruleInfo.getVersion().getSnapshot());
}
});
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("snopshot", jsonObject);
logger.info("===========================监控添加策略信息快照情况:{}",jsonObject1);
outMap.put("strategySnopshot", jsonObject1);
}
/**
* 串行执行规则
*
* @param inputParam
* @param outMap
* @param ruleInfoList
* @param ruleResultList
* @return
*/
private List<RuleInfo> serialRule(Map<String, Object> inputParam, Map<String, Object> outMap, List<RuleInfo> ruleInfoList, CopyOnWriteArrayList<Map> ruleResultList) {
logger.info("请求参数--串行执行规则" + "map:" + JSONObject.toJSONString(inputParam));
List<RuleInfo> resultList = new ArrayList<>();
for (int i = 0; i < ruleInfoList.size(); i++) {
RuleInfo rule = ruleInfoList.get(i);
boolean hitFlag = executeByDifficulty(inputParam, outMap, rule, ruleResultList);
if (hitFlag) {
resultList.add(rule);
break;
}
}
return resultList;
}
/**
* 并行执行规则
*
* @param inputParam
* @param outMap
* @param ruleInfoList
* @param ruleResultList
* @return
*/
private List<RuleInfo> parallelRule(Map<String, Object> inputParam, Map<String, Object> outMap, List<RuleInfo> ruleInfoList, CopyOnWriteArrayList<Map> ruleResultList) {
logger.info("请求参数--并行执行规则" + "map:" + JSONObject.toJSONString(inputParam));
List<RuleInfo> resultList = new ArrayList<>();
List<CompletableFuture<RuleInfo>> futureList = new ArrayList<>();
for (int i = 0; i < ruleInfoList.size(); i++) {
final int index = i;
CompletableFuture<RuleInfo> future = CompletableFuture.supplyAsync(() -> {
RuleInfo rule = ruleInfoList.get(index);
boolean hitFlag = executeByDifficulty(inputParam, outMap, rule, ruleResultList);
if (hitFlag) {
return rule;
} else {
return null;
}
}, threadPoolTaskExecutor);
futureList.add(future);
}
for (CompletableFuture<RuleInfo> future : futureList) {
try {
RuleInfo rule = future.get();
if (rule != null) {
resultList.add(rule);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return resultList;
}
/**
* 根究规则类型选择执行
*
* @param inputParam
* @param outMap
* @param rule
* @param ruleResultList
* @return
*/
private boolean executeByDifficulty(Map<String, Object> inputParam, Map<String, Object> outMap, RuleInfo rule, CopyOnWriteArrayList<Map> ruleResultList) {
boolean hitFlag = false;
if (rule.getDifficulty() == 2) {
hitFlag = executeComplexRule(inputParam, outMap, rule, ruleResultList);
} else if (rule.getDifficulty() == 3) {
hitFlag = executeScriptRule(inputParam, outMap, rule, ruleResultList);
}
return hitFlag;
}
/**
* 执行复杂规则
*
* @param input
* @param output
* @param rule
* @param ruleResultList
* @return
*/
public boolean executeComplexRule(Map<String, Object> input, Map<String, Object> output, RuleInfo rule, CopyOnWriteArrayList<Map> ruleResultList) {
boolean hitFlag = false;
//获取需要执行的整个规则。
// RuleVo rule = ruleService.queryByVersionId(ruleId);
// Long versionId = rule.getVersionId();
// if (versionId==null){
// return false;
// }
// RuleVersionVo ruleVersion = versionService.queryByVersionId(versionId);
RuleVersionVo ruleVersion = rule.getVersion();
if (ruleVersion == null) {
return false;
}
//取出本规则的条件列表
Map<String, Object> ruleMap = new HashMap<>();
ruleMap.put("ruleId", rule.getId());
ruleMap.put("ruleVersionId",ruleVersion.getId());
ruleMap.put("ruleCode", rule.getCode());
ruleMap.put("ruleName", rule.getName());
ruleMap.put("versionCode", ruleVersion.getVersionCode());
ruleMap.put("versionDesc", ruleVersion.getDescription());
ruleMap.put("desc", rule.getDescription());
ruleMap.put("ruleResult", "未命中");
//获取规则需要执行的condition逻辑。
RuleConditionVo ruleCondition = ruleVersion.getRuleConditionVo();
//传入输入参数、中间变量、输出参数和需要执行的condition逻辑获取执行结果
Map<String, Object> temp = JSON.parseObject(JSON.toJSONString(input), Map.class);
boolean result = this.executeRuleCondition(temp, output, ruleCondition);
String resultFieldEn = ruleVersion.getResultFieldEn();
if (resultFieldEn == null || "".equals(resultFieldEn)) {
resultFieldEn = "rule_2_"+rule.getId()+"_"+ruleVersion.getId()+"_hitResult";
}
String scoreFieldEn = ruleVersion.getScoreFieldEn();
if (StringUtils.isBlank(scoreFieldEn)){
scoreFieldEn = "rule_2_"+rule.getId()+"_"+ruleVersion.getId()+"_score";
}
input.put(resultFieldEn, "未命中");
//根据执行的最终结果处理此规则输出内容
List<JSONObject> fieldList = new ArrayList<>();
JSONObject resultJson = new JSONObject();
if (result) {
ruleMap.put("ruleResult", "命中");
ruleMap.put("ruleScore", rule.getScore());
JSONObject scoreJson = new JSONObject();
resultJson.put(resultFieldEn, "命中");
fieldList.add(resultJson);
// if (StringUtils.isNotBlank(ruleVersion.getScoreFieldEn())) {
scoreJson.put(scoreFieldEn, ruleVersion.getScore());
fieldList.add(scoreJson);
input.put(scoreFieldEn, ruleVersion.getScore());
// }
input.put(resultFieldEn, "命中");
//处理此规则需要输出的内容
fieldList.addAll(ruleService.setComplexRuleOutput(ruleVersion.getId(), temp, input, StrategyType.OutType.SUCCESS_OUT));
ruleMap.put("fieldList", fieldList);
hitFlag = true;
} else {
resultJson.put(resultFieldEn, "未命中");
ruleMap.put("ruleScore", 0);
input.put(scoreFieldEn,0);
fieldList.add(resultJson);
fieldList.addAll(ruleService.setComplexRuleOutput(ruleVersion.getId(), temp, input, StrategyType.OutType.FAIL_OUT));
ruleMap.put("fieldList", fieldList);
}
ruleResultList.add(ruleMap);
return hitFlag;
}
//执行规则的条件
private boolean executeRuleCondition(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
Integer conditionType = ruleCondition.getConditionType();
boolean result = false;
switch (conditionType) {
//关系条件节点 &&和||
case RuleConst.RELATION_CONDITION:
//循环结果的条件
case RuleConst.LOOP_RESULT_CONDITION:
case RuleConst.CONDITION_RESULT_CONDITION:
result = executeRelation(input, output, ruleCondition);
break;
//表达式条件节点
case RuleConst.EXPRESSION_CONDITION:
result = executeExpression(input, output, ruleCondition);
break;
//循环条件根节点
case RuleConst.LOOP_CONDITION:
result = executeLoop(input, output, ruleCondition);
break;
//条件组根节点
case RuleConst.CONDITION_GROUP_CONDITION:
result = executeCondGroup(input, output, ruleCondition);
break;
}
return result;
}
//执行条件组
private boolean executeCondGroup(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
//取出子条件
List<RuleConditionVo> children = ruleCondition.getChildren();
//存储命中条数
int hitNum = 0;
if (children == null) {
return false;
}
//执行条件组中条件列表,命中则添加命中条数
for (RuleConditionVo child : children) {
boolean childResult = executeRuleCondition(input, output, child);
if (childResult) {
hitNum++;
}
}
//获取条件组命中条件为null直接不命中
RuleConditionVo condGroup = ruleCondition.getCondGroupResultCondition();
if (condGroup == null) {
return false;
}
//传入命中条件和组内命中条数执行并返回
Map<String, Object> map = new HashMap<>();
//将命中条数存入map然后判断执行结果
map.put("hitNum", hitNum);
return executeRuleCondition(map, output, condGroup);
}
//关系条件节点 &&和||
private boolean executeRelation(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
//获取关系逻辑
String logical = ruleCondition.getLogical();
//处理子逻辑
List<RuleConditionVo> children = ruleCondition.getChildren();
boolean result = false;
switch (logical) {
case "||":
result = false;
for (RuleConditionVo child : children) {
boolean childResult = executeRuleCondition(input, output, child);
if (childResult) {
return true;
}
}
break;
case "&&":
result = true;
for (RuleConditionVo child : children) {
boolean childResult = executeRuleCondition(input, output, child);
if (!childResult) {
return false;
}
}
break;
}
return result;
}
//表达式条件节点
private boolean executeExpression(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
String executionLogic = ruleCondition.getExecutionLogic();
boolean result = false;
ExpressionParam expressionParam = new ExpressionParam();
//复制执行的关键参数到统一入参
BeanUtils.copyProperties(ruleCondition, expressionParam);
result = ExecuteUtils.getExpressionResult(expressionParam, input);
return result;
}
//循环条件根节点
private boolean executeLoop(Map<String, Object> input, Map<String, Object> output, RuleConditionVo ruleCondition) {
List<RuleConditionVo> children = ruleCondition.getChildren();
String fieldEn = ruleCondition.getFieldEn();
//对循环中每个条件进行处理
String[] split = fieldEn.split("\\.");
//从map中取元素返回最终取到的对象
Object obj = ExecuteUtils.getObjFromMap(input, fieldEn);
List arrayList = new ArrayList();
if (obj != null) {
arrayList.addAll(JSON.parseObject(JSON.toJSONString(obj), ArrayList.class));
}
//取不到这个数组
if (arrayList.isEmpty()) {
return false;
}
//拼接当前对象的key
String currentKey = "%" + split[split.length - 1] + "%";
for (RuleConditionVo child : children) {
List<RuleLoopGroupAction> loopGroupActions = child.getLoopGroupActions();
// 调用for循环条件下的操作,并且将其存入input中
for (RuleLoopGroupAction loopGroupAction : loopGroupActions) {
this.initLoopGroupAction(loopGroupAction, input);
}
}
for (Object currentObj : arrayList) {
//将循环时的当前对象存入input
input.put(currentKey, currentObj);
//循环执行当前for中的每个判断单元
for (RuleConditionVo child : children) {
if (executeRuleCondition(input, output, child)) {
List<RuleLoopGroupAction> loopGroupActions = child.getLoopGroupActions();
// 调用for循环条件下的操作,并且将其存入input中
for (RuleLoopGroupAction loopGroupAction : loopGroupActions) {
this.saveLoopGroupAction(loopGroupAction, input);
}
}
}
}
//计算for的返回结果
RuleConditionVo loopResultCondition = ruleCondition.getLoopResultCondition();
boolean result = executeRuleCondition(input, output, loopResultCondition);
return result;
}
//保存循环规则的动作
private void saveLoopGroupAction(RuleLoopGroupAction loopGroupAction, Map<String, Object> input) {
Integer actionType = loopGroupAction.getActionType();
String actionKey = loopGroupAction.getActionKey();
String actionValue = loopGroupAction.getActionValue();
if (actionType == null) {
return;
}
switch (actionType) {
case RuleConst.LOOP_GROUP_ACTION_TYPE_SUM:
Integer count = 1;
if (input.containsKey(actionKey) && StringUtils.isNumeric(ExecuteUtils.getObjFromMap(input, actionKey).toString())) {
count = count + Integer.parseInt(ExecuteUtils.getObjFromMap(input, actionKey).toString());
}
input.put(actionKey, count);
break;
case RuleConst.LOOP_GROUP_ACTION_TYPE_ASSIGNMENT:
//赋值待添加
break;
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_CONST:
input.put(actionKey, actionValue);
break;
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_VARIABLE:
input.put(actionKey, ExecuteUtils.getObjFromMap(input, actionValue));
break;
}
}
private void initLoopGroupAction(RuleLoopGroupAction loopGroupAction, Map<String, Object> input){
Integer actionType = loopGroupAction.getActionType();
String actionKey = loopGroupAction.getActionKey();
String actionValue = loopGroupAction.getActionValue();
if (actionType == null) {
return;
}
switch (actionType) {
case RuleConst.LOOP_GROUP_ACTION_TYPE_SUM:
input.put(actionKey, 0);
break;
case RuleConst.LOOP_GROUP_ACTION_TYPE_ASSIGNMENT:
//赋值待添加
break;
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_CONST:
input.put(actionKey, "");
break;
case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_VARIABLE:
input.put(actionKey,new HashSet<>());
break;
}
}
/**
* 终止条件判断
*
* @param engineNode
* @param inputParam
* @param outMap
* @param ruleHitList
*/
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap, List<RuleInfo> ruleHitList) {
if (StringUtils.isBlank(engineNode.getNodeScript())) {
return;
}
JSONObject nodeScript = JSONObject.parseObject(engineNode.getNodeScript());
JSONObject terminationInfo = nodeScript.getJSONObject("terminationInfo");
JSONArray selectedRule = terminationInfo.getJSONArray("selectedRule");
String conditions = terminationInfo.getString("conditions");
if (!selectedRule.isEmpty()) {
if (!selectedRule.isEmpty()) {
List<JSONObject> selectedRuleList = JSONObject.parseArray(JSONObject.toJSONString(selectedRule), JSONObject.class);
// 查找已选规则中命名的规则集合
List<RuleInfo> selectedHitRules = new ArrayList<>();
for (JSONObject jsonObject : selectedRuleList) {
Optional<RuleInfo> rule = ruleHitList.stream().filter(item -> item.getId().equals(jsonObject.getLong("id"))).findFirst();
if (rule.isPresent()) {
selectedHitRules.add(rule.get());
}
}
int totalSize = selectedHitRules.size(); // 规则命名个数
double totalScore = selectedHitRules.stream().mapToDouble(RuleInfo::getScore).sum(); // 规则总得分
String sizeKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_size";
String scoreKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_score";
Map<String, Object> variablesMap = new HashMap<>();
variablesMap.put(sizeKey, totalSize);
variablesMap.put(scoreKey, totalScore);
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap,variablesMap);
}
}
}
private List<RuleInfo> getRuleFromJsonArray(JSONArray jsonArray) {
List<Long> ruleIds = new ArrayList<>();
Map<Long, Long> map = new HashMap<>();
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject ruleObj = jsonArray.getJSONObject(i);
Long versionId = ruleObj.getLong("ruleVersionId");
Long ruleId = ruleObj.getLong("id");
if (ruleId != null) {
ruleIds.add(ruleId);
if (versionId != null) {
map.put(ruleId, versionId);
}
}
}
List<RuleInfo> ruleInfoList = ruleService.getRuleList(ruleIds);
for (RuleInfo ruleInfo : ruleInfoList) {
if (ruleInfo.getDifficulty() == 2 || ruleInfo.getDifficulty() == 3) {
Long versionId = map.get(ruleInfo.getId());
ruleInfo.setVersionId(versionId);
if (versionId != null) {
switch (ruleInfo.getDifficulty()) {
case 2:
RuleVersionVo ruleVersionVo = versionService.queryById(versionId);
ruleInfo.setVersion(ruleVersionVo);
ruleInfo.setScore(ruleVersionVo.getScore());
break;
case 3:
RuleScriptVersion ruleScriptVersion = ruleScriptVersionService.queryById(versionId);
ruleInfo.setScriptVersion(ruleScriptVersion);
ruleInfo.setVersion(JSON.parseObject(JSON.toJSONString(ruleScriptVersion), RuleVersionVo.class));
ruleInfo.setScore(0);
break;
}
} else {
ruleInfo.setScore(0);
}
}
}
return ruleInfoList;
}
/**
* 执行脚本规则
*
* @param inputParam
* @param outMap
* @param rule
* @param ruleResultList
* @return
*/
private boolean executeScriptRule(Map<String, Object> inputParam, Map<String, Object> outMap, RuleInfo rule, CopyOnWriteArrayList<Map> ruleResultList) {
boolean hitFlag = false;
RuleScriptVersion scriptVersion = rule.getScriptVersion();
if (RuleConst.ScriptType.GROOVY.equals(rule.getScriptType())&&RuleConst.ScriptType.GROOVY.equals( scriptVersion.getScriptType())) {
//groovy脚本执行
//取出需要执行的版本
if (scriptVersion == null || StringUtils.isBlank(scriptVersion.getScriptContent())) {
return false;
}
//取出脚本内容
String scriptContent = scriptVersion.getScriptContent();
//取出本规则集的规则列表
Map<String, Object> ruleMap = new HashMap<>();
ruleMap.put("ruleId", rule.getId());
ruleMap.put("ruleVersionId",scriptVersion.getId());
ruleMap.put("ruleCode", rule.getCode());
ruleMap.put("ruleName", rule.getName());
ruleMap.put("versionCode", scriptVersion.getVersionCode());
ruleMap.put("versionDesc", scriptVersion.getDescription());
ruleMap.put("desc", rule.getDescription());
ruleMap.put("ruleResult", "未命中");
String resultFieldEn = "hitResult";
String resultEn = "rule_"+rule.getDifficulty()+"_"+rule.getId()+"_"+scriptVersion.getId()+"_hitResult";
String scoreEn = "rule_"+rule.getDifficulty()+"_"+rule.getId()+"_"+scriptVersion.getId()+"_score";
inputParam.put(resultEn, "未命中");
inputParam.put(scoreEn,0);
//根据执行的最终结果处理此规则输出内容
List fieldList = new ArrayList<>();
JSONObject resultJson = new JSONObject();
try {
Object resp = ExecuteUtils.getObjFromScript(inputParam, scriptContent);
String result = "未命中";
JSONObject executeResult = null;
int ruleScore = 0;
if (resp instanceof HashMap) {
Map resultMap = (HashMap) resp;
executeResult = JSON.parseObject(JSON.toJSONString(resultMap));
ruleScore = executeResult.getIntValue("ruleScore");
result = executeResult.getString(resultFieldEn);
JSONArray fieldListJson = executeResult.getJSONArray("fieldList");
JSONObject updateInputMap = executeResult.getJSONObject("updateInputMap");
if (fieldListJson != null) {
fieldList = fieldListJson.toJavaList(Object.class);
List list = new ArrayList();
for (Object o : fieldList) {
if (o!=null&& o instanceof Map){
Map map = ExecuteUtils.handleGroovyResult((Map) o);
list.add(map);
}
}
fieldList = list;
}
if (executeResult != null) {
ruleMap.put("ruleResult", result);
ruleMap.put("ruleScore", ruleScore);
resultJson.put(resultFieldEn, result);
fieldList.add(resultJson);
inputParam.put(resultFieldEn, result);
//处理此规则需要输出的内容
ruleMap.put("fieldList", fieldList);
}
if ("命中".equals(result)) {
hitFlag = true;
inputParam.put(resultEn,"命中");
inputParam.put(scoreEn,ruleScore);
}
//更新入参
if (updateInputMap!=null&&!updateInputMap.isEmpty()){
Set<Map.Entry<String, Object>> entries = ExecuteUtils.handleGroovyResult(updateInputMap).entrySet();
for (Map.Entry<String, Object> entry : entries) {
inputParam.put(entry.getKey(),entry.getValue());
}
}
}
} catch (Exception e) {
e.printStackTrace();
logger.error("脚本规则集执行错误:{}" + e);
}
ruleResultList.add(ruleMap);
}
return hitFlag;
}
// public static void main(String[] args) {
//// HashMap<String, Object> result = new HashMap<>(); //规则执行的返回值
//// int ruleScore = 0; //规则命中时得分
//// String hitResult = "未命中"; //命中结果,可选类型为:命中、未命中
//// HashMap<String, Object> updateInputMap = new HashMap<>(); //用于更新入参的map此map中的所有内容将被更新到入参中,key重复的将被覆盖。
//// ArrayList<HashMap<String, Object>> fieldList = new ArrayList<>(); //用于存放输出字段的值
//// //自定义代码区域,根据需要书写逻辑代码
////
////
////
//// //返回固定格式的结果用于后续执行
//// result.put("hitResult",hitResult);
//// result.put("ruleScore",ruleScore);
//// result.put("fieldList",fieldList);
//// result.put("updateInputMap",updateInputMap);
//// return result;
// }
}

View File

@@ -0,0 +1,114 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.model.enginex.runner.Sandbox;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@Service
public class SandboxProportionNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
if (null != engineNode.getNodeScript()) {
List<Sandbox> list = JSON.parseArray(engineNode.getNodeScript(), Sandbox.class);
//监控中心-- 节点配置信息记录(不需要策略层面的监控)
JSONObject nodeSnapshot = new JSONObject();
nodeSnapshot.put("nodeSnapshot",JSON.parseArray(engineNode.getNodeJson()));
outMap.put("nodeSnapshot",nodeSnapshot);
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode",engineNode);
nodeInfo.put("nodeId",engineNode.getNodeId());
nodeInfo.put("nodeName",engineNode.getNodeName());
nodeInfo.put("nodeType",engineNode.getNodeType());
outMap.put("nodeInfo",nodeInfo);
int num = 0;//随机生成的数
int startNum = 0;
int endNum = 0;
for (int i = 0; i < list.size(); i++) {
Sandbox sandbox = list.get(i);
endNum = startNum + sandbox.getProportion();
if (num == 0)
num = getRandoms(0, sandbox.getSum(), 1)[0];
int[] range = getRandoms(startNum, endNum, sandbox.getProportion());
for (int j = 0; j < range.length; j++) {
if (range[j] == num) {
if (StringUtils.isBlank(sandbox.getNextNode())) {
List<Sandbox> sblist = JSON.parseArray(engineNode.getNodeJson(), Sandbox.class);
for (Sandbox sb : sblist) {
if (sb.getSandbox() == sandbox.getSandbox()) {
sandbox.setNextNode(sb.getNextNode());
break;
}
}
}
outMap.put("nextNode", sandbox.getNextNode());
JSONObject nodeResult = new JSONObject();
nodeResult.put("nodeResult",sandbox.getNextNode());
outMap.put("nodeResult",nodeResult);
break;
}
}
startNum = endNum;
}
}
}
/**
* 根据min和max随机生成count个不重复的随机数组
*
* @param min
* @param max
* @param count
* @return int[]
*/
public int[] getRandoms(int min, int max, int count) {
int[] randoms = new int[count];
List<Integer> listRandom = new ArrayList<Integer>();
if (count > (max - min + 1)) {
return null;
}
// 将所有的可能出现的数字放进候选list
for (int i = min; i < max; i++) {
listRandom.add(i);
}
// 从候选list中取出放入数组已经被选中的就从这个list中移除
for (int i = 0; i < count; i++) {
int index = getRandom(0, listRandom.size() - 1);
randoms[i] = listRandom.get(index);
listRandom.remove(index);
}
return randoms;
}
/**
* 根据min和max随机生成一个范围在[min,max]的随机数包括min和max
*
* @param min
* @param max
* @return int
*/
public int getRandom(int min, int max) {
Random random = new Random();
return random.nextInt(max - min + 1) + min;
}
}

View File

@@ -0,0 +1,264 @@
package com.fibo.ddp.enginex.runner.node.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fibo.ddp.common.model.datax.datamanage.Field;
import com.fibo.ddp.common.model.enginex.risk.EngineNode;
import com.fibo.ddp.common.model.strategyx.scorecard.ScorecardDetail;
import com.fibo.ddp.common.model.strategyx.scorecard.ScorecardDimension;
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardDetailVo;
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardDimensionVo;
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardVersionVo;
import com.fibo.ddp.common.model.strategyx.scorecard.vo.ScorecardVo;
import com.fibo.ddp.common.service.datax.datamanage.FieldService;
import com.fibo.ddp.common.service.datax.runner.CommonService;
import com.fibo.ddp.common.service.datax.runner.ExecuteUtils;
import com.fibo.ddp.common.service.strategyx.scorecard.ScorecardDetailService;
import com.fibo.ddp.common.service.strategyx.scorecard.ScorecardDimensionService;
import com.fibo.ddp.common.service.strategyx.scorecard.ScorecardService;
import com.fibo.ddp.common.utils.util.runner.JevalUtil;
import com.fibo.ddp.common.utils.util.runner.StrUtils;
import com.fibo.ddp.common.utils.util.runner.jeval.EvaluationException;
import com.fibo.ddp.enginex.runner.node.EngineRunnerNode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class ScorecardNode implements EngineRunnerNode {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private CommonService commonService;
@Resource
public FieldService fieldService;
@Resource
public ScorecardService scorecardService;
@Autowired
private ScorecardDimensionService scorecardDimensionService; // 维度
@Autowired
private ScorecardDetailService scorecardDetailService; // 明细
private List<Long> getExecuteVersionIdList(EngineNode engineNode) {
return ExecuteUtils.getExecuteIdList(engineNode,"versionId");
}
@Override
public void getNodeField(EngineNode engineNode, Map<String, Object> inputParam) {
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
Set<Long> fieldIdSet = new HashSet<>();
for (Long versionId : versionIdList) {
List<ScorecardDimension> scorecardDimensions = scorecardDimensionService.getDimensionListByVersionId(versionId);
List<Integer> dimensionIds = scorecardDimensions.stream().map(item -> item.getId()).collect(Collectors.toList());
List<ScorecardDetail> scorecardDetails = scorecardDetailService.getDetailListByDimensionIds(dimensionIds);
fieldIdSet.addAll(scorecardDetails.stream().map(item -> Long.valueOf(item.getFieldId().toString())).collect(Collectors.toSet()));
}
List<Long> ids = new ArrayList<>(fieldIdSet);
commonService.getFieldByIds(ids, inputParam);
}
@Override
public void runNode(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap) {
//监控中心--节点快照信息
if (engineNode != null && engineNode.getSnapshot() != null) {
outMap.put("nodeSnapshot", engineNode.getSnapshot());
}
List<Long> versionIdList = getExecuteVersionIdList(engineNode);
for (Long versionId : versionIdList) {
ScorecardVo scorecard = scorecardService.queryExecuteScorecard(versionId);
JSONObject nodeInfo = new JSONObject();
nodeInfo.put("engineNode", engineNode);
nodeInfo.put("nodeId", engineNode.getNodeId());
nodeInfo.put("nodeName", engineNode.getNodeName());
nodeInfo.put("nodeType", engineNode.getNodeType());
outMap.put("nodeInfo", nodeInfo);
List<ScorecardDetail> hitDetailList = new ArrayList<>(); // 命中的评分字段列表
ScorecardVersionVo versionVo = scorecard.getExecuteVersion();
List<ScorecardDimensionVo> scorecardDimensions = new ArrayList<>();
if (versionVo != null) {
//监控中心 == 策略层面快照信息
if (versionVo != null && versionVo.getSnapshot() != null) {
outMap.put("scorecardStrategy", versionVo.getSnapshot());
}
scorecardDimensions = versionVo.getScorecardDimension();
for (ScorecardDimensionVo scorecardDimensionVo : scorecardDimensions) {
List<ScorecardDetailVo> scorecardDetailVoList = scorecardDimensionVo.getChildren();
scorecardHit(hitDetailList, 0, scorecardDetailVoList, inputParam);
}
}
Double totalScore = 0d;
List<JSONObject> scoreDetail = new ArrayList<>();
for (ScorecardDimension scorecardDimension : scorecardDimensions) {
Double dimensionScore = 0d;
JSONObject jsonObject = new JSONObject();
jsonObject.put("dimensionName", scorecardDimension.getDimensionName());
jsonObject.put("dimensionId", scorecardDimension.getId());
for (ScorecardDetail scorecardDetail : hitDetailList) {
if (!scorecardDetail.getDimensionId().equals(scorecardDimension.getId())) {
continue;
}
String fieldEn = scorecardDetail.getFieldEn();
Integer scoreCalculateType = scorecard.getScoreCalculateType();
Integer calculateType = scorecardDetail.getCalculateType();
// 计算方式为 得分
if (calculateType == 1) {
if (scoreCalculateType == 1) { // 评分计算方式为 求和
Double value = scorecardDetail.getScore();
totalScore += value;
dimensionScore += value;
} else if (scoreCalculateType == 2) { // 评分计算方式为 加权求和
Double value = scorecardDetail.getScore() * scorecardDimension.getWeight();
totalScore += value;
dimensionScore += value;
}
}
// 计算方式为 系数
else if (calculateType == 2) {
if (scoreCalculateType == 1) { // 评分计算方式为 求和
Double value = Double.valueOf(inputParam.get(fieldEn).toString()) * scorecardDetail.getCoefficient();
totalScore += value;
dimensionScore += value;
} else if (scoreCalculateType == 2) { // 评分计算方式为 加权求和
Double value = Double.valueOf(inputParam.get(fieldEn).toString()) * scorecardDetail.getCoefficient() * scorecardDimension.getWeight();
totalScore += value;
dimensionScore += value;
}
}
// 计算方式为 自定义
else if (calculateType == 3) {
double value = 0d;
String custom = scorecardDetail.getCustom();
if (custom != null && !"".equals(custom)) {
Double result = StrUtils.strToDouble(ExecuteUtils.getObjFromScript(inputParam, custom).toString());
if (result != null) {
value = result;
}
}
totalScore += value;
dimensionScore += value;
}
}
jsonObject.put("score", dimensionScore);
scoreDetail.add(jsonObject);
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("nodeId", engineNode.getNodeId());
jsonObject.put("nodeName", engineNode.getNodeName());
jsonObject.put("cardId", scorecard.getId());
jsonObject.put("cardName", scorecard.getName());
jsonObject.put("cardCode", scorecard.getCode());
String versionCode = "";
Long cardVersionId = null;
if (versionVo != null) {
versionCode = versionVo.getVersionCode();
cardVersionId = versionVo.getId();
}
jsonObject.put("cardVersion", versionCode);
jsonObject.put("cardVersionId",cardVersionId);
jsonObject.put("desc", scorecard.getDescription());
jsonObject.put("score", totalScore);
jsonObject.put("scoreDetail", scoreDetail);
//给入参中放入评分卡执行结果
String resultFieldEn = versionVo.getResultFieldEn();
if (StringUtils.isBlank(resultFieldEn)) {
resultFieldEn = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_" + versionVo.getId() + "_score";
}
inputParam.put(resultFieldEn, totalScore);
inputParam.put(scorecard.getCode(), totalScore);
List<JSONObject> fieldList = new ArrayList<>();
JSONObject scoreResult = new JSONObject();
scoreResult.put(resultFieldEn, totalScore);
fieldList.add(scoreResult);
if (totalScore != 0) {
List<JSONObject> jsonObjects = scorecardService.setOutput(scorecard.getId(), inputParam);
fieldList.addAll(jsonObjects);
}
jsonObject.put("fieldList", fieldList);
//监控中心==》将评分卡的执行结果得分明细放入 输出变量池 用于存入hbase
outMap.put("nodeResult", jsonObject);
if (outMap.containsKey("scoreJson")) {
JSONArray resultJson = (JSONArray) outMap.get("scoreJson");
resultJson.add(jsonObject);
} else {
JSONArray resultJson = new JSONArray();
resultJson.add(jsonObject);
outMap.put("scoreJson", resultJson);
}
terminalCondition(engineNode,inputParam,outMap,totalScore);
}
}
/**
* 评分卡命中判断
*
* @param hitDetailList
* @param detailId
* @param scorecardDetailVoList
* @param inputParam
*/
private void scorecardHit(List<ScorecardDetail> hitDetailList, Integer detailId, List<ScorecardDetailVo> scorecardDetailVoList, Map<String, Object> inputParam) {
List<ScorecardDetailVo> scorecardDetailVos = scorecardDetailVoList.stream().filter(item -> item.getParentId().equals(detailId)).collect(Collectors.toList());
for (ScorecardDetailVo scorecardDetailVo : scorecardDetailVos) {
Field field = fieldService.queryById(Long.valueOf(scorecardDetailVo.getFieldId()));
String fieldEn = field.getFieldEn();
scorecardDetailVo.setFieldEn(fieldEn);
String condition = scorecardDetailVo.getCondition();
Boolean isHit = isScoreFieldValue(inputParam, fieldEn, condition);
if (isHit) {
if (scorecardDetailVo.getType() == 1) {
hitDetailList.add(scorecardDetailVo);
} else {
this.scorecardHit(hitDetailList, scorecardDetailVo.getId(), scorecardDetailVoList, inputParam);
}
}
}
}
/**
* 评分卡字段是否在区间内
*
* @param map
* @param fieldCode
* @param condition
* @return
*/
private Boolean isScoreFieldValue(Map<String, Object> map, String fieldCode, String condition) {
if ("(,)".equals(condition)) {
return true;
}
String exp = JevalUtil.getNumericInterval(condition, fieldCode);
try {
if (JevalUtil.evaluateBoolean(exp, map)) {
return true;
}
} catch (EvaluationException e) {
e.printStackTrace();
logger.error("请求异常", e);
}
return false;
}
private void terminalCondition(EngineNode engineNode, Map<String, Object> inputParam, Map<String, Object> outMap,Object executeResult) {
String resultKey = engineNode.getNodeType() + "_" + engineNode.getNodeId() + "_terminal_score";
Map<String,Object> map = new HashMap<>();
map.put(resultKey,executeResult);
ExecuteUtils.terminalCondition(engineNode,inputParam,outMap, map);
}
}