|
|
@@ -0,0 +1,421 @@
|
|
|
+package com.usky.data.service.util;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.usky.data.domain.DataInterface;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 接口执行器,用于处理不同类型接口的执行逻辑
|
|
|
+ * <p>
|
|
|
+ * 支持三种接口类型:
|
|
|
+ * 1. SQL操作(type=1)
|
|
|
+ * 2. 静态数据(type=2)
|
|
|
+ * 3. API操作(type=3)
|
|
|
+ * </p>
|
|
|
+ */
|
|
|
+public class InterfaceExecutor {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行接口逻辑,参考原始infoToId方法
|
|
|
+ *
|
|
|
+ * @param dataInterface 接口实体
|
|
|
+ * @param params 请求参数
|
|
|
+ * @return 执行结果
|
|
|
+ */
|
|
|
+ public static Object executeInterface(DataInterface dataInterface, Map<String, Object> params) {
|
|
|
+ if (dataInterface == null) {
|
|
|
+ throw new IllegalArgumentException("接口配置不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换params为Map<String, String>用于参数处理
|
|
|
+ Map<String, String> stringParams = new HashMap<>();
|
|
|
+ if (params != null) {
|
|
|
+ params.forEach((k, v) -> stringParams.put(k, v != null ? v.toString() : null));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 替换默认值
|
|
|
+ replaceDefaultValue(dataInterface.getParameterJson(), stringParams);
|
|
|
+
|
|
|
+ // 验证参数必填或类型
|
|
|
+ String checkResult = checkRequestParams(dataInterface.getParameterJson(), stringParams);
|
|
|
+ if (StringUtils.isNotEmpty(checkResult)) {
|
|
|
+ throw new IllegalArgumentException(checkResult);
|
|
|
+ }
|
|
|
+
|
|
|
+ Object result = null;
|
|
|
+ try {
|
|
|
+ // 根据接口类型执行不同逻辑
|
|
|
+ Integer type = dataInterface.getType();
|
|
|
+ switch (type) {
|
|
|
+ case 1:
|
|
|
+ // 静态数据
|
|
|
+ result = callStaticData(dataInterface.getDataConfigJson());
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ // API调用
|
|
|
+ result = callApi(dataInterface.getDataConfigJson(), stringParams);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ // SQL操作
|
|
|
+ result = executeSql(dataInterface, stringParams);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new IllegalArgumentException("不支持的接口类型: " + type);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理结果,执行JS脚本
|
|
|
+ if (StringUtils.isNotEmpty(dataInterface.getDataJsJson())) {
|
|
|
+ // 这里模拟JS脚本执行,实际项目中需要引入JS引擎
|
|
|
+ result = processResult(result, dataInterface.getDataJsJson());
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("接口执行失败: " + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 替换默认值
|
|
|
+ *
|
|
|
+ * @param parameterJson 参数配置JSON
|
|
|
+ * @param params 请求参数
|
|
|
+ */
|
|
|
+ private static void replaceDefaultValue(String parameterJson, Map<String, String> params) {
|
|
|
+ if (StringUtils.isEmpty(parameterJson)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONArray paramArray = JSON.parseArray(parameterJson);
|
|
|
+ if (paramArray == null || paramArray.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (Object obj : paramArray) {
|
|
|
+ JSONObject paramObj = (JSONObject) obj;
|
|
|
+ String field = paramObj.getString("field");
|
|
|
+ String defaultValue = paramObj.getString("defaultValue");
|
|
|
+
|
|
|
+ // 如果参数中没有该字段或值为空,则设置默认值
|
|
|
+ if (!params.containsKey(field) || StringUtils.isEmpty(params.get(field))) {
|
|
|
+ params.put(field, defaultValue == null ? "" : defaultValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查请求参数
|
|
|
+ *
|
|
|
+ * @param parameterJson 参数配置JSON
|
|
|
+ * @param params 请求参数
|
|
|
+ * @return 检查结果,空字符串表示通过
|
|
|
+ */
|
|
|
+ private static String checkRequestParams(String parameterJson, Map<String, String> params) {
|
|
|
+ if (StringUtils.isEmpty(parameterJson)) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONArray paramArray = JSON.parseArray(parameterJson);
|
|
|
+ if (paramArray == null || paramArray.isEmpty()) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuilder message = new StringBuilder();
|
|
|
+ for (Object obj : paramArray) {
|
|
|
+ JSONObject paramObj = (JSONObject) obj;
|
|
|
+
|
|
|
+ // 验证必填字段
|
|
|
+ Integer required = paramObj.getInteger("required");
|
|
|
+ if (required != null && required == 1) {
|
|
|
+ String field = paramObj.getString("field");
|
|
|
+ String value = params.get(field);
|
|
|
+ if (StringUtils.isEmpty(value)) {
|
|
|
+ message.append(field).append("不能为空;");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证数据类型
|
|
|
+ String dataType = paramObj.getString("dataType");
|
|
|
+ if (StringUtils.isNotEmpty(dataType)) {
|
|
|
+ String field = paramObj.getString("field");
|
|
|
+ String value = params.get(field);
|
|
|
+ if (StringUtils.isEmpty(value)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if ("int".equals(dataType)) {
|
|
|
+ Integer.parseInt(value);
|
|
|
+ } else if ("decimal".equals(dataType)) {
|
|
|
+ Double.parseDouble(value);
|
|
|
+ } else if ("datetime".equals(dataType)) {
|
|
|
+ try {
|
|
|
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+ formatter.parse(value);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 尝试解析时间戳
|
|
|
+ Long.parseLong(value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ message.append(field).append("类型必须为").append(dataType).append(";");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return message.length() > 0 ? message.substring(0, message.length() - 1) : "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行静态数据类型接口
|
|
|
+ *
|
|
|
+ * @param dataConfigJson 数据配置JSON
|
|
|
+ * @return 静态数据结果
|
|
|
+ */
|
|
|
+ private static Object callStaticData(String dataConfigJson) {
|
|
|
+ JSONObject configJson = JSON.parseObject(dataConfigJson);
|
|
|
+ String staticData = configJson.getString("staticData");
|
|
|
+
|
|
|
+ Object obj;
|
|
|
+ try {
|
|
|
+ Object parse = JSON.parse(staticData);
|
|
|
+ if (parse instanceof JSONArray) {
|
|
|
+ obj = JSON.parseArray(staticData, Map.class);
|
|
|
+ } else {
|
|
|
+ obj = JSON.parseObject(staticData, Map.class);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ obj = staticData;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (obj == null) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ return obj;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行API类型接口
|
|
|
+ *
|
|
|
+ * @param dataConfigJson 数据配置JSON
|
|
|
+ * @param params 请求参数
|
|
|
+ * @return API调用结果
|
|
|
+ */
|
|
|
+ private static Object callApi(String dataConfigJson, Map<String, String> params) {
|
|
|
+ JSONObject configJson = JSON.parseObject(dataConfigJson);
|
|
|
+ JSONObject apiData = configJson.getJSONObject("apiData");
|
|
|
+
|
|
|
+ if (apiData == null) {
|
|
|
+ throw new IllegalArgumentException("API配置不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String url = apiData.getString("url");
|
|
|
+ String method = apiData.getString("method");
|
|
|
+ JSONObject headers = apiData.getJSONObject("headers");
|
|
|
+ JSONObject apiParams = apiData.getJSONObject("params");
|
|
|
+
|
|
|
+ // 合并参数
|
|
|
+ if (apiParams == null) {
|
|
|
+ apiParams = new JSONObject();
|
|
|
+ }
|
|
|
+ if (params != null) {
|
|
|
+ JSONObject finalApiParams = apiParams;
|
|
|
+ params.forEach((k, v) -> {
|
|
|
+ if (StringUtils.isNotEmpty(v)) {
|
|
|
+ finalApiParams.put(k, v);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟API调用,实际项目中需要使用HTTP客户端
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+ result.put("success", true);
|
|
|
+ result.put("message", "API调用成功");
|
|
|
+ result.put("data", apiParams);
|
|
|
+ result.put("url", url);
|
|
|
+ result.put("method", method);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行SQL类型接口
|
|
|
+ *
|
|
|
+ * @param dataInterface 接口实体
|
|
|
+ * @param params 请求参数
|
|
|
+ * @return SQL执行结果
|
|
|
+ */
|
|
|
+ private static Object executeSql(DataInterface dataInterface, Map<String, String> params) {
|
|
|
+ JSONObject configJson = JSON.parseObject(dataInterface.getDataConfigJson());
|
|
|
+ JSONObject sqlData = configJson.getJSONObject("sqlData");
|
|
|
+
|
|
|
+ if (sqlData == null) {
|
|
|
+ throw new IllegalArgumentException("SQL配置不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String sql = sqlData.getString("sql");
|
|
|
+ if (StringUtils.isEmpty(sql)) {
|
|
|
+ throw new IllegalArgumentException("SQL语句不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 替换SQL中的参数占位符
|
|
|
+ sql = replaceSqlParams(sql, params);
|
|
|
+
|
|
|
+ // 模拟SQL执行结果
|
|
|
+ List<Map<String, Object>> resultList = new ArrayList<>();
|
|
|
+ for (int i = 0; i < 5; i++) {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("id", i + 1);
|
|
|
+ map.put("name", "测试数据" + (i + 1));
|
|
|
+ map.put("value", i * 100);
|
|
|
+ map.put("created_at", "2026-01-24 10:00:00");
|
|
|
+ resultList.add(map);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是分页查询,处理分页信息
|
|
|
+ if (dataInterface.getHasPage() != null && dataInterface.getHasPage() == 1) {
|
|
|
+ Map<String, Object> pageResult = new HashMap<>();
|
|
|
+ pageResult.put("list", resultList);
|
|
|
+ pageResult.put("total", 100);
|
|
|
+ pageResult.put("current", params.getOrDefault("currentPage", "1"));
|
|
|
+ pageResult.put("pageSize", params.getOrDefault("pageSize", "20"));
|
|
|
+ return pageResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 替换SQL中的参数占位符
|
|
|
+ *
|
|
|
+ * @param sql SQL语句
|
|
|
+ * @param params 请求参数
|
|
|
+ * @return 替换后的SQL语句
|
|
|
+ */
|
|
|
+ private static String replaceSqlParams(String sql, Map<String, String> params) {
|
|
|
+ if (StringUtils.isEmpty(sql) || params == null || params.isEmpty()) {
|
|
|
+ return sql;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 匹配 {参数名} 格式的占位符
|
|
|
+ Pattern pattern = Pattern.compile("\\{(\\w+)\\}");
|
|
|
+ Matcher matcher = pattern.matcher(sql);
|
|
|
+
|
|
|
+ StringBuffer sb = new StringBuffer();
|
|
|
+ while (matcher.find()) {
|
|
|
+ String paramName = matcher.group(1);
|
|
|
+ String paramValue = params.getOrDefault(paramName, "");
|
|
|
+ matcher.appendReplacement(sb, paramValue);
|
|
|
+ }
|
|
|
+ matcher.appendTail(sb);
|
|
|
+
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理结果,执行JS脚本
|
|
|
+ *
|
|
|
+ * @param result 原始结果
|
|
|
+ * @param jsScript JS脚本
|
|
|
+ * @return 处理后的结果
|
|
|
+ */
|
|
|
+ private static Object processResult(Object result, String jsScript) {
|
|
|
+ // 这里模拟JS脚本执行,实际项目中需要引入JS引擎
|
|
|
+ // 例如使用javax.script.ScriptEngine
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断是否为内部接口返回格式
|
|
|
+ *
|
|
|
+ * @param jsonObject JSON对象
|
|
|
+ * @return 是否为内部接口格式
|
|
|
+ */
|
|
|
+ private static boolean isInternal(JSONObject jsonObject) {
|
|
|
+ if (jsonObject != null) {
|
|
|
+ return jsonObject.size() == 3 &&
|
|
|
+ jsonObject.containsKey("code") &&
|
|
|
+ jsonObject.containsKey("msg") &&
|
|
|
+ jsonObject.containsKey("data");
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取接口字段信息
|
|
|
+ *
|
|
|
+ * @param dataInterface 接口实体
|
|
|
+ * @param params 请求参数
|
|
|
+ * @return 接口字段列表
|
|
|
+ */
|
|
|
+ public static List<String> getInterfaceFields(DataInterface dataInterface, Map<String, Object> params) {
|
|
|
+ // 执行接口获取数据
|
|
|
+ Object result = executeInterface(dataInterface, params);
|
|
|
+
|
|
|
+ // 解析结果获取字段列表
|
|
|
+ List<String> fields = new ArrayList<>();
|
|
|
+ if (result instanceof List) {
|
|
|
+ List<?> resultList = (List<?>) result;
|
|
|
+ if (!resultList.isEmpty() && resultList.get(0) instanceof Map) {
|
|
|
+ Map<?, ?> firstItem = (Map<?, ?>) resultList.get(0);
|
|
|
+ for (Object key : firstItem.keySet()) {
|
|
|
+ fields.add(key.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (result instanceof Map) {
|
|
|
+ Map<?, ?> resultMap = (Map<?, ?>) result;
|
|
|
+ // 如果是分页结果,获取list中的字段
|
|
|
+ if (resultMap.containsKey("list") && resultMap.get("list") instanceof List) {
|
|
|
+ List<?> list = (List<?>) resultMap.get("list");
|
|
|
+ if (!list.isEmpty() && list.get(0) instanceof Map) {
|
|
|
+ Map<?, ?> firstItem = (Map<?, ?>) list.get(0);
|
|
|
+ for (Object key : firstItem.keySet()) {
|
|
|
+ fields.add(key.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 直接获取map中的字段
|
|
|
+ for (Object key : resultMap.keySet()) {
|
|
|
+ fields.add(key.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return fields;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取接口分页数据
|
|
|
+ *
|
|
|
+ * @param dataInterface 接口实体
|
|
|
+ * @param params 请求参数
|
|
|
+ * @return 分页数据结果
|
|
|
+ */
|
|
|
+ public static Map<String, Object> getInterfacePageData(DataInterface dataInterface, Map<String, Object> params) {
|
|
|
+ // 执行接口获取数据
|
|
|
+ Object result = executeInterface(dataInterface, params);
|
|
|
+
|
|
|
+ // 处理分页
|
|
|
+ Map<String, Object> pageResult = new HashMap<>();
|
|
|
+
|
|
|
+ if (result instanceof Map && ((Map<?, ?>) result).containsKey("list")) {
|
|
|
+ // 如果已经是分页格式,直接返回
|
|
|
+ pageResult.putAll((Map<? extends String, ?>) result);
|
|
|
+ } else {
|
|
|
+ // 否则包装成分页格式
|
|
|
+ pageResult.put("list", result);
|
|
|
+ pageResult.put("total", result instanceof List ? ((List<?>) result).size() : 1);
|
|
|
+ pageResult.put("current", params != null ? params.getOrDefault("currentPage", 1) : 1);
|
|
|
+ pageResult.put("pageSize", params != null ? params.getOrDefault("pageSize", 20) : 20);
|
|
|
+ }
|
|
|
+
|
|
|
+ return pageResult;
|
|
|
+ }
|
|
|
+}
|