7.5 消费方应用接入方式

​ 在UDM中消费方(规则调用方)应用接入方式通常有2种:(1)Http rest方式直接请求规则管理端http服务,(2)SDK方式通过java api调用并执行规则包。

7.5.1 Http rest方式

启用规则包Http服务

启用当前规则包对外的Http Rest服务功能,用于控制第三方消费者是否允许调用指定的rest服务接口

image-20260104154419209

调用示例

  • RuleApp规则包在线模拟测试
{
  "empVar": {
    "age": 27,
    "sex": "男"
  }
}

image-20260104154101980

  • 三方http测试工具模拟测试

image-20260104154345591

7.5.2 SDK方式

消费方应用程序须依赖udm-core组件

<dependency>
    <groupId>com.bstek.udm</groupId>
    <artifactId>udm-core</artifactId>
    <version>${udm-core.version}</version>
    <exclusions>
        <exclusion>
            <artifactId>commons-logging</artifactId>
            <groupId>commons-logging</groupId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>io.github.classgraph</groupId>
    <artifactId>classgraph</artifactId>
    <version>${classgraph.version}</version>
</dependency>

调用java api接口执行决策

  • 获取规则包字节流
String base64ZipTestFileContent=null; // TODO 开发者自行实现,规则包从哪儿获取到:数据库udm_ruleapp_version中 / 缓存中
  • 构建规则执行会话对象
byte[] decodedBytes = Base64.getDecoder().decode(base64ZipTestFileContent);
InputStream inputStream = new ByteArrayInputStream(decodedBytes);
KnowledgeArchive knowledgeArchive =new InputStreamKnowledgeArchive(inputStream, new Date().getTime());
KnowledgeSession knowledgeSession = KnowledgeService.INSTANCE.newSession(knowledgeArchive);
Map<String, ObjectValue> inputDataMap = (Map<String, ObjectValue>) buildInputData(map);
  • 构建输入数据
Map<String, Object> empVarMap = new HashMap<>();
// FIXME 请开发者修改成实际业务数据
empVarMap.put("age",20);
// 处理输入数据
Map<String, ObjectValue> inputDataMap = KnowledgeHelper.buildInputData(empVarMap, knowledgeSession);
// 以下3个方为固定写法,直接复制即可
public static Map<String, ObjectValue> buildInputData(Map<String, Object> map, KnowledgeSession knowledgeSession) {
    ClassLoader classLoader = knowledgeSession.getKnowledgeClassLoader();
    Map<String, Variable> inputVariables = knowledgeSession.getKnowledgeInputVariables();
    Map<String, ObjectValue> inputDataMap = new HashMap<>();
    for (Map.Entry<String, Object> entry : map.entrySet()) {
        String key = "'" + entry.getKey() + "'";
        if (!inputVariables.containsKey(key)) {
            //当前当前输入的变量不在当前关联的知识包中的输入变量中,那么就直接忽略
            continue;
        }
        Object value = entry.getValue();
        Variable variable = inputVariables.get(key);
        String datatype = variable.getType();
        Class<?> clazz = ReflectionUtils.loadTargetClass(datatype, classLoader);
        //先判断当前clazz是否为简单类型
        if (ClassUtils.isSimpleType(clazz)) {
            //当前clazz为简单类型,那么就直接构建出当前的ObjectValue
            value = ReflectionUtils.buildValueByType(value, clazz);
            ObjectValue objectValue = new ObjectValue(value, clazz.getName());
            inputDataMap.put(key, objectValue);
        } else {
            Object obj = newInstanceByClass(clazz);
            Map<String, Object> mapValue = (Map<String, Object>) value;
            buildObject(mapValue, obj);
            ObjectValue objectValue = new ObjectValue(obj, clazz.getName());
            inputDataMap.put(key, objectValue);
        }
    }
    return inputDataMap;
}

@SuppressWarnings("unchecked")
private static void buildObject(Map<String, Object> mapValue, Object obj) {
    for (Map.Entry<String, Object> entry : mapValue.entrySet()) {
        String fieldName = entry.getKey();
        if (fieldName.equals(DATATYPE_KEY)) {
            //当前字段为客户端提交上来的标识类型的字段,那么就直接忽略
            continue;
        }
        Object fieldValue = entry.getValue();
        //获取当前对象对应的字段属性类型
        Class<?> propertyTypeClass = ReflectionUtils.getPropertyType(fieldName, obj.getClass());
        if (ClassUtils.isSimpleType(propertyTypeClass)) {
            //当前属性为简单类型,那么就根据类型转换一下当前的fieldValue
            Object newValue = ReflectionUtils.buildValueByType(fieldValue, propertyTypeClass);
            //将转换后的值设置到当前的对象中
            ReflectionUtils.setObjectPropertyValue(obj, fieldName, newValue);
        } else if (List.class.isAssignableFrom(propertyTypeClass)) {
            //当前属性为列表类型,那么就递归调用buildObject方法
            List<Object> list = new ArrayList<>();
            //尝试从属性类型里获取泛型类型
            Class<?> genericTypeClass = propertyTypeClass.getComponentType();
            if (genericTypeClass == null) {
                //如果当前列表类型没有指定泛型类型,那么就直接忽略
                continue;
            }
            if (fieldValue instanceof List) {
                //如果当前值为列表类型,那么就循环取出列表中的每个元素的值
                for (Object item : (List<Object>) fieldValue) {
                    //判断泛型类型是否为简单类型,如果是则直接转换当前值为简单类型
                    Object value = item;
                    if (ClassUtils.isSimpleType(genericTypeClass)) {
                        value = ReflectionUtils.buildValueByType(value, genericTypeClass);
                        list.add(value);
                    } else if (item instanceof Map) {
                        //如果当前项目为Map类型,那么就递归调用buildObject方法
                        Object subObject = newInstanceByClass(genericTypeClass);
                        buildObject((Map<String, Object>) item, subObject);
                        list.add(subObject);
                    }
                }
            } else {
                //当前值不是列表,那么就需要根据泛型类型创建一个新的对象
                Object value = ReflectionUtils.buildValueByType(fieldValue, genericTypeClass);
                list.add(value);
            }
            ReflectionUtils.setObjectPropertyValue(obj, fieldName, list);
        } else {
            //当前属性为复杂对象类型,那么就递归调用buildObject方法
            Object subObject = newInstanceByClass(propertyTypeClass);
            buildObject((Map<String, Object>) fieldValue, subObject);
            ReflectionUtils.setObjectPropertyValue(obj, fieldName, subObject);
        }
    }
}

private static Object newInstanceByClass(Class<?> clazz) {
    if (clazz.isInterface()) {
        //如果当前clazz是一个接口类,那么就尝试扫描对应的实现类
        try (ScanResult scanResult = new ClassGraph().enableAllInfo().scan()) {
            List<Class<?>> classes = scanResult.getSubclasses(clazz.getName()).loadClasses();
            Class<?> targetClazz = null;
            for (Class<?> c : classes) {
                //找到一个非接口非抽象类的类
                if (!c.isInterface() && !Modifier.isAbstract(c.getModifiers())) {
                    targetClazz = c;
                    break;
                }
            }
            if (targetClazz != null) {
                //如果存在实现类,那么就取第一个实现类
                clazz = targetClazz;
            } else {
                throw new RuleException("接口类" + clazz.getName() + "不存在对应的实现类");
            }
        } catch (Exception e) {
            //对应的类型不存在,那么就直接抛出异常
            throw new RuleException(e);
        }
    }
    try {
        return clazz.newInstance();
    } catch (Exception e) {
        throw new RuleException(e);
    }
}
  • 执行规则匹配,返回决策结果
// 执行匹配
ExecutionConfiguration configuration = new ExecutionConfiguration(true);
CollectionLogListener collectionLogListener = new CollectionLogListener();
configuration.addListener(collectionLogListener);
KnowledgeSessionResponse response = knowledgeSession.execute(inputDataMap, configuration);
// 读取匹配结果
Map<String, Object> outputParameters = response.getOutputParameters();
Map<String, Object> resultMap = new HashMap<>();// 重新包装规则匹配结果
resultMap.put("log", collectionLogListener.getRootLog());
resultMap.put("output", outputParameters);
resultMap.put("elapse", response.getExecutionDuration());

results matching ""

    No results matching ""