Sfoglia il codice sorgente

自定义异常、修改批量插入的方法、按照不同的情况返回不同的错误

JoeLazy 1 mese fa
parent
commit
5e9064ea2e
32 ha cambiato i file con 892 aggiunte e 426 eliminazioni
  1. 8 3
      src/main/java/com/sundata/internalevaluation/calc/calcUnit/DataSetCalcUnit.java
  2. 1 1
      src/main/java/com/sundata/internalevaluation/calc/calcUnit/IndexCalcUnit.java
  3. 29 60
      src/main/java/com/sundata/internalevaluation/calc/calcUnit/InterfaceCalcUnit.java
  4. 0 194
      src/main/java/com/sundata/internalevaluation/calc/calcUnit/InterfaceParamCalcUnit.java
  5. 15 0
      src/main/java/com/sundata/internalevaluation/calc/calcUnit/interfaces/AddressInterfaceRunningService.java
  6. 111 7
      src/main/java/com/sundata/internalevaluation/calc/custom/GetDataTest.java
  7. 80 0
      src/main/java/com/sundata/internalevaluation/calc/exception/CalcConfigException.java
  8. 67 0
      src/main/java/com/sundata/internalevaluation/calc/exception/CalcParentException.java
  9. 66 0
      src/main/java/com/sundata/internalevaluation/calc/exception/DataException.java
  10. 81 0
      src/main/java/com/sundata/internalevaluation/calc/exception/RequestParamException.java
  11. 80 0
      src/main/java/com/sundata/internalevaluation/calc/exception/ResponseDataException.java
  12. 79 0
      src/main/java/com/sundata/internalevaluation/calc/exception/SendRequestException.java
  13. 22 3
      src/main/java/com/sundata/internalevaluation/calc/model/CalcUnit.java
  14. 4 0
      src/main/java/com/sundata/internalevaluation/calc/model/interfaces/Calc.java
  15. 55 7
      src/main/java/com/sundata/internalevaluation/calc/running/CalcRunning.java
  16. 21 1
      src/main/java/com/sundata/internalevaluation/calc/running/threads/CalcTaskResult.java
  17. 1 1
      src/main/java/com/sundata/internalevaluation/calc/running/threads/fianl/CalcTaskResultType.java
  18. 1 1
      src/main/java/com/sundata/internalevaluation/calc/util/CalciteUtil.java
  19. 6 1
      src/main/java/com/sundata/internalevaluation/configuration/controller/RiskControlStrategyAction.java
  20. 4 6
      src/main/java/com/sundata/internalevaluation/configuration/mapper/DataSourcesMapper.java
  21. 1 1
      src/main/java/com/sundata/internalevaluation/configuration/mapper/IndexConfigMapper.java
  22. 0 8
      src/main/java/com/sundata/internalevaluation/configuration/mapper/RuleMapper.java
  23. 3 3
      src/main/java/com/sundata/internalevaluation/configuration/mapper/RuleSetMapper.java
  24. 10 0
      src/main/java/com/sundata/internalevaluation/configuration/model/InputParamModel.java
  25. 39 64
      src/main/java/com/sundata/internalevaluation/configuration/mybatis/DataSourcesMapper.xml
  26. 12 21
      src/main/java/com/sundata/internalevaluation/configuration/mybatis/IndexConfigMapper.xml
  27. 0 10
      src/main/java/com/sundata/internalevaluation/configuration/mybatis/RuleMapper.xml
  28. 3 8
      src/main/java/com/sundata/internalevaluation/configuration/mybatis/RuleSetMapper.xml
  29. 64 21
      src/main/java/com/sundata/internalevaluation/configuration/service/DataSourcesService.java
  30. 18 2
      src/main/java/com/sundata/internalevaluation/configuration/service/IndexConfigService.java
  31. 10 2
      src/main/java/com/sundata/internalevaluation/configuration/service/RuleSetService.java
  32. 1 1
      src/main/java/com/sundata/internalevaluation/script/execute/TemplateExecute.java

+ 8 - 3
src/main/java/com/sundata/internalevaluation/calc/calcUnit/DataSetCalcUnit.java

@@ -7,9 +7,12 @@ import com.sundata.internalevaluation.calc.model.CalcException;
 import com.sundata.internalevaluation.calc.model.CalcResult;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.model.finals.CalcType;
+import com.sundata.internalevaluation.calc.util.CalciteUtil;
 import com.sundata.internalevaluation.configuration.model.DataSetModel;
 import com.sundata.internalevaluation.configuration.model.DataSourceModel;
 import com.sundata.internalevaluation.configuration.service.DataSourcesService;
+import org.apache.calcite.adapter.file.JsonScannableTable;
+import org.apache.calcite.schema.impl.AbstractSchema;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -128,14 +131,16 @@ public class DataSetCalcUnit extends CalcUnit {
         log.info("当前计算节点为:[{}-{}-{}],计算流水号为:{}", this.getCalcType(), this.getCalcCode(), this.getCalcName(), calculateInstanceNumber);
         // TODO 实际的计算过程
         // 合并后结果集
-        Map<String,Object> resultMap = new HashMap<>();
+        Map<String, JsonScannableTable> resultMap = new HashMap<>();
         // 合并数据集
         sourceResults.forEach((calcUnit,result)-> {
-            resultMap.putAll(result);
+            Map<String, JsonScannableTable> item = (Map<String, JsonScannableTable>) result.get(calcUnit.getCalcCode());
+            resultMap.putAll(item);
         });
         log.debug("合并后结果集结构:{}",resultMap);
+        AbstractSchema schema = CalciteUtil.createSchema(resultMap);
         // 合并数据集结果集放入
-        thisResult.put(this.getCalcCode(),resultMap);
+        thisResult.put(this.getCalcCode(),schema);
 
     }
 

+ 1 - 1
src/main/java/com/sundata/internalevaluation/calc/calcUnit/IndexCalcUnit.java

@@ -190,7 +190,7 @@ public class IndexCalcUnit extends CalcUnit {
                     } else {
                         String errorMsg = StrUtil.format("数据集-[{}({})]-返回的计算结果不是AbstractSchema类型",calcUnit.getCalcName(),calcCode);
                         log.error(errorMsg);
-                        throw new CalcException(errorMsg);
+                        throw new CalcException(calculateInstanceNumber, errorMsg);
                     }
 
                 }

+ 29 - 60
src/main/java/com/sundata/internalevaluation/calc/calcUnit/InterfaceCalcUnit.java

@@ -7,10 +7,10 @@ import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONException;
 import cn.hutool.json.JSONUtil;
-import com.sundata.common.exception.BusinessException;
 import com.sundata.common.util.JsonUtil;
 import com.sundata.internalevaluation.calc.calcUnit.interfaces.InterfaceRunning;
-import com.sundata.internalevaluation.calc.model.CalcException;
+import com.sundata.internalevaluation.calc.exception.CalcConfigException;
+import com.sundata.internalevaluation.calc.exception.SendRequestException;
 import com.sundata.internalevaluation.calc.model.CalcResult;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.model.finals.CalcType;
@@ -139,7 +139,7 @@ public class InterfaceCalcUnit extends CalcUnit {
         // 请求类型不为 http或者 https   或者   请求体不为 json
         if (!interfaceTypeCode.startsWith("http") || !"json".equals(reqContentTypeCode)) {
             // TODO Socket 请求
-            throw new BusinessException("目前仅支持http和https的请求和json请求体");
+            throw new CalcConfigException("目前仅支持http和https的请求和json请求体");
         }
 
         // 请求参数实体列表
@@ -224,8 +224,8 @@ public class InterfaceCalcUnit extends CalcUnit {
                 log.debug("接口-[{}({})]-请求地址-[{}]-响应body报文:{}",getCalcName(),getCalcCode(),url,responseStr);
             }catch (Exception e){
                 String errMsg = StrUtil.format("接口-[{}({})]-请求地址-[{}] - 请求出现异常:{}", getCalcName(), getCalcCode(), url, e.getMessage());
-                log.error(errMsg);
-                throw new BusinessException(errMsg, e);
+                log.error(errMsg,e);
+                throw new SendRequestException("请求发送失败:["+url+"]", e);
             }
 
             // 判断返回值类型
@@ -235,13 +235,13 @@ public class InterfaceCalcUnit extends CalcUnit {
                     responseStr = JSONUtil.toJsonPrettyStr(responseStr);
                 } catch (JSONException e) {
                     log.error("接口-[{}({})]-请求地址-[{}] - 返回值不是程序能解析的json字符串,请检查!", getCalcName(), getCalcCode(), url);
-                    throw new CalcException(calculateInstanceNumber, "返回值不是程序能解析的json字符串,请检查!");
+                    throw new CalcConfigException("返回值不是程序能解析的json字符串,请检查!",e);
                 }
             }
             // TODO 可继续增加其他类型
             else
             {
-                throw new RuntimeException("接口-目前只支持 json 返回报文");
+                throw new CalcConfigException("接口-目前只支持 json 返回报文");
             }
 
 
@@ -306,13 +306,18 @@ public class InterfaceCalcUnit extends CalcUnit {
     }
 
 
-
-    private Object getParamValue(InterfaceParam sysInterfaceParam, Map<String, Object> context) {
+    /**
+     * 获取请求参数的值
+     * @param interfaceParam 请求参数实体
+     * @param context 调用计算单元传入的值
+     * @return 参数结果
+     */
+    private Object getParamValue(InterfaceParam interfaceParam, Map<String, Object> context) {
         // 参数获取类型
-        String paramRetrievalTypeCode = sysInterfaceParam.getParamRetrievalTypeCode();
+        String paramRetrievalTypeCode = interfaceParam.getParamRetrievalTypeCode();
 
         // 参数获取内容
-        String paramRetrievalTypeCont = sysInterfaceParam.getParamRetrievalTypeCont();
+        String paramRetrievalTypeCont = interfaceParam.getParamRetrievalTypeCont();
 
         Object result = null;
 
@@ -330,31 +335,36 @@ public class InterfaceCalcUnit extends CalcUnit {
                 try {
                     result = InvokeUtil.invokeMethod(paramRetrievalTypeCont);
                 } catch (Exception e) {
-                    throw new RuntimeException(e);
+                    String errorMsg = StrUtil.format("接口(参数)-[{}({})]-通过Java获取参数失败,对应方法为:[{}]", getCalcName(), interfaceParam.getParamObjName(), paramRetrievalTypeCont);
+                    log.error(errorMsg);
+                    throw new CalcConfigException(errorMsg,e);
                 }
                 break;
             // SQL-Map
             case "sqlmap":
                 String sqlMap = TemplateUtil.execute("interfaceParam-temp-sqlmap-" + getCalcCode(), paramRetrievalTypeCont, context);
-                log.warn("sql语句为:{}",sqlMap);
+                log.debug("通过SQL-Map获取接口参数:{}",sqlMap);
                 result = jdbcTemplate.queryForMap(sqlMap);
                 break;
             // SQL-List
             case "sqllist":
                 String sqlList = TemplateUtil.execute("interfaceParam-temp-sqllist-" + getCalcCode(), paramRetrievalTypeCont, context);
-                log.warn("sql语句为:{}",sqlList);
+                log.debug("通过SQL-Map获取接口参数:{}",sqlList);
                 result = jdbcTemplate.queryForList(sqlList);
                 break;
             // SQL-String
             case "sqlstring":
                 String sqlString = TemplateUtil.execute("interfaceParam-temp-sqlstring-" + getCalcCode(), paramRetrievalTypeCont, context);
-                log.warn("sql语句为:{}",sqlString);
+                log.debug("通过SQL-Map获取接口参数:{}",sqlString);
                 result = jdbcTemplate.queryForObject(sqlString, Object.class);
                 break;
+            case "callerInput":
+                result = TemplateUtil.execute("interfaceParam-temp-callerInput-"+getCalcCode(),paramRetrievalTypeCont, context);
+                break;
         }
 
 
-        String paramTypeCode = sysInterfaceParam.getParamTypeCode();
+        String paramTypeCode = interfaceParam.getParamTypeCode();
         if ("string".equals(paramTypeCode)) {
             if (result instanceof String) {
 
@@ -376,55 +386,14 @@ public class InterfaceCalcUnit extends CalcUnit {
                 } else if (result instanceof Byte) {
                     result = ((Number) result).byteValue();
                 } else {
-                    throw new RuntimeException("数据类型不匹配:计算机过不为'数字'");
+                    throw new CalcConfigException("数据类型不匹配:计算机过不为'数字'");
                 }
-
             } else {
-                throw new RuntimeException("数据类型不匹配:计算机过不为'数字'");
+                throw new CalcConfigException("数据类型不匹配:计算机过不为'数字'");
             }
         } else {
-            throw new CalcException("返回值类型有无,目前仅有 数字和字符串");
+            throw new CalcConfigException("返回值类型有误,目前仅有 数字和字符串");
         }
         return result;
     }
-
-
-    /**
-     *
-     * @param url
-     * @param bodyStr
-     * @param allParam
-     * @return
-     */
-//    private String sendRequestBySDKAPI (String url, String bodyStr, HashMap<String,Object> allParam) {
-//        Object publicKey = allParam.get("publicKey");
-//        if (publicKey == null) {
-//            throw new RuntimeException("publicKey 不能为空");
-//        }
-//        Object systemCode = allParam.get("systemCode");
-//        if (systemCode == null) {
-//            throw new RuntimeException("systemCode 不能为空");
-//        }
-//
-//        // 构建发送请求客户端
-//        ApiClient apiClient = ApiClient.builder().apiUrl(url)
-//                .publicKey(publicKey)
-//                .systemCode(systemCode)
-//                .build();
-//
-//        // 构建json反序列化为MyApiRequest 对象
-//        MyApiRequest apiRequest = JSONUtil.toBean(bodyStr,MyApiRequest.class);
-//        String jsonPrettyStr = JSONUtil.toJsonPrettyStr(apiRequest);
-//        // 相应信息
-//        ApiResponse<JSONObject> response = apiRequest.excute(apiClient);
-//        String jsonStr = JSONUtil.toJsonStr(response);
-//        return jsonStr;
-//    }
-//
-////    private static class MyApiRequest extends ApiRequest<HashMap<String,Object>, JSONObject> {
-//        public MyApiRequest() {
-//            super.setResponseDataClass(JSONObject.class);
-//        }
-//    }
-
 }

+ 0 - 194
src/main/java/com/sundata/internalevaluation/calc/calcUnit/InterfaceParamCalcUnit.java

@@ -1,194 +0,0 @@
-package com.sundata.internalevaluation.calc.calcUnit;
-
-import com.sundata.common.util.DBExecutor;
-import com.sundata.common.util.JsonUtil;
-import com.sundata.internalevaluation.calc.model.CalcException;
-import com.sundata.internalevaluation.calc.model.CalcResult;
-import com.sundata.internalevaluation.calc.model.CalcUnit;
-import com.sundata.internalevaluation.calc.model.finals.CalcType;
-import com.sundata.internalevaluation.calc.util.InvokeUtil;
-import com.sundata.internalevaluation.configuration.model.InterfaceParam;
-import com.sundata.internalevaluation.script.TemplateUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Created by IntelliJ IDEA.
- *
- * @author JoeLazy
- * @date 2025-02-13 16:23:55
- * @description: 接口参数计算单元
- */
-public class InterfaceParamCalcUnit extends CalcUnit {
-
-    private static final Logger log = LoggerFactory.getLogger(InterfaceParamCalcUnit.class);
-
-    /**
-     * 接口参数实体
-     */
-
-    private final InterfaceParam interfaceParam;
-
-    /**
-     * 创建数据单元的绝对对象,对象必须包含如下参数
-     *
-     * @param calcCode    计算对象编号
-     * @param calcName    计算对象名称
-     * @param calcType    计算类型
-     * @param initContext 计算单元初始化参数
-     */
-    public InterfaceParamCalcUnit(String calcCode, String calcName, CalcType calcType, Map<String, Object> initContext, InterfaceParam interfaceParam) {
-        super(calcCode, calcName, calcType, initContext);
-        this.interfaceParam = interfaceParam;
-    }
-
-    /**
-     * 判断是否已经计算过数据了
-     *
-     * @param calculateInstanceNumber 计算流水号
-     * @return 是否计算过 true 计算过 false 没有计算过
-     */
-    @Override
-    public boolean isCalcFinished(String calculateInstanceNumber) {
-        return false;
-    }
-
-    /**
-     * 初始化计算结果的方法,如果已经计算过,在实现过程中,应当在此方法中根据计算流水号重新初始化 resultContext 结果对象,为其他依赖对象做准备
-     * 若明明计算过本单元但再次计算时没有初始化该对象,则计算依赖出现问题无法定位与处理
-     *
-     * @param calculateInstanceNumber 计算流水号
-     */
-    @Override
-    public void initResultContext(String calculateInstanceNumber) {
-
-    }
-
-    /**
-     * 根据节点配置获取源节点;
-     *
-     * @return 所有源头节点
-     */
-    @Override
-    public List<CalcUnit> getSourceCalcUnits() {
-        return List.of();
-    }
-
-    /**
-     * 计算之后的方法,可实现为空
-     *
-     * @param context
-     */
-    @Override
-    public void afterCalc(Map<String, Object> context) {
-
-    }
-
-    /**
-     * 计算之前,可实现空
-     *
-     * @param context
-     */
-    @Override
-    public void beforeCalc(Map<String, Object> context) {
-
-    }
-
-    /**
-     * 必须实现的主体计算内容
-     *
-     * @param thisResult              本计算单元的结果
-     * @param calculateInstanceNumber 计算流水号
-     * @param context                 节点计算参数清单
-     * @param sourceResults           源头计算节点的结果
-     */
-    @Override
-    public void calc(CalcResult<String, Object> thisResult, String calculateInstanceNumber, Map<String, Object> context, Map<CalcUnit, CalcResult<String, Object>> sourceResults) {
-
-
-        log.debug("计算{}:编号:{},名称:{},流水号:{}", getCalcType().getName(),getCalcCode(),getCalcName(),calculateInstanceNumber);
-
-
-        // 参数获取类型
-        String paramRetrievalTypeCode = interfaceParam.getParamRetrievalTypeCode();
-
-        // 参数获取内容
-        String paramRetrievalTypeCont = interfaceParam.getParamRetrievalTypeCont();
-
-
-        Object result = null;
-
-        // 获取参数值
-        switch (paramRetrievalTypeCode) {
-            // 固定值
-            case "fixed":
-                result = paramRetrievalTypeCont;
-                break;
-            // java
-            //   获取参数内容
-            case "java":
-                try {
-                    result = InvokeUtil.invokeMethod(paramRetrievalTypeCont);
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-                break;
-            // SQL-Map
-            case "sqlmap":
-                String execute = TemplateUtil.execute("interfaceParam-temp-sqlmap-" + getCalcCode(), paramRetrievalTypeCont, context);
-                log.warn("sql语句为:{}",execute);
-                result = DBExecutor.doQuery(execute);
-                break;
-            // SQL-List
-            case "sqllist":
-                String execute1 = TemplateUtil.execute("interfaceParam-temp-sqllist-" + getCalcCode(), paramRetrievalTypeCont, context);
-                log.warn("sql语句为:{}",execute1);
-                result = DBExecutor.doQueryMapList(execute1);
-                break;
-            // SQL-String
-            case "sqlstring":
-                String execute2 = TemplateUtil.execute("interfaceParam-temp-sqlstring-" + getCalcCode(), paramRetrievalTypeCont, context);
-                log.warn("sql语句为:{}",execute2);
-                result = DBExecutor.doQuery(execute2);
-                break;
-        }
-
-
-        String paramTypeCode = this.interfaceParam.getParamTypeCode();
-        if ("string".equals(paramTypeCode)) {
-            if (result instanceof String) {
-
-            } else {
-                result = JsonUtil.toJSONString(result);
-            }
-        } else if ("number".equals(paramTypeCode)) {
-            if (result instanceof Number) {
-                if (result instanceof Integer) {
-                    result = ((Number) result).intValue();
-                } else if (result instanceof Long) {
-                    result = ((Number) result).longValue();
-                } else if (result instanceof Float) {
-                    result = ((Number) result).floatValue();
-                } else if (result instanceof Double) {
-                    result = ((Number) result).doubleValue();
-                } else if (result instanceof Short) {
-                    result = ((Number) result).shortValue();
-                } else if (result instanceof Byte) {
-                    result = ((Number) result).byteValue();
-                } else {
-                    throw new RuntimeException("数据类型不匹配:计算机过不为'数字'");
-                }
-
-            } else {
-                throw new RuntimeException("数据类型不匹配:计算机过不为'数字'");
-            }
-        } else {
-            throw new CalcException("返回值类型有无,目前仅有 数字和字符串");
-        }
-        thisResult.put(getCalcCode(), result);
-        thisResult.put("entity", interfaceParam);
-    }
-}

+ 15 - 0
src/main/java/com/sundata/internalevaluation/calc/calcUnit/interfaces/AddressInterfaceRunningService.java

@@ -47,7 +47,22 @@ public class AddressInterfaceRunningService implements InterfaceRunning{
      */
     @Override
     public String afterDecode(String interfaceNo, String interfaceStr, String calculateInstanceNumber) {
+
         return JsonUtil.toJSONString(Map.of(interfaceNo, List.of(JsonUtil.jsonToMap(interfaceStr))));
+
+//        // ************************ 举例
+//        Map<String, Object> resMap = JSONUtil.toBean(interfaceStr, Map.class);
+//        Object resCode = resMap.get("resCode");
+//        // 判断是否请求成功返回正常的数据
+//        if ("200".equals(resCode)){
+//            // 解析数据的逻辑
+//            // ......
+//
+//            // 返回解析后的数据
+//            // return .... ;
+//        }else{
+//            throw new ResponseDataException(String.valueOf(resMap.get("resMsg")));
+//        }
     }
 
     /**

+ 111 - 7
src/main/java/com/sundata/internalevaluation/calc/custom/GetDataTest.java

@@ -1,9 +1,11 @@
 package com.sundata.internalevaluation.calc.custom;
 
+import cn.hutool.core.util.RandomUtil;
+import com.sundata.internalevaluation.script.ScriptUtil;
+import com.sundata.internalevaluation.script.TemplateUtil;
+
 import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 /**
  * Created by IntelliJ IDEA.
@@ -106,14 +108,116 @@ public class GetDataTest {
 
 
     public static void main(String[] args) {
-        String sql = "select * from a where a = ${a} and b = ${b} and c =${a}";
-        Map<String, Object> map = new HashMap<>();
+//        String sql = "select * from a where a = ${a} and b = ${b} and c =${a}";
+//        Map<String, Object> map = new HashMap<>();
+//
+//        map.put("a", "isA");
+//        map.put("b", "isB");
+
+//        Map<String, Object> map = new HashMap<>();
+//        map.put("isStaff", 0);
+//        map.put("isEmployrecord", 0);
+//        map.put("isBankBlack", 1);
+//        map.put("isIntro", 0);
+//        map.put("isCredit", false);
+//        map.put("str", "qiao");
+//        String script = "${isStaff}==1 || ${isEmployrecord}==1 || ${isBankBlack}==1 || ${isIntro} ==1";
+//        script = "isCredit==true";
+//        script = "'${str}'=='qiao'";
+//        script = TemplateUtil.execute(UUID.randomUUID().toString(), script, map);
+//        Object o = ScriptUtil.executeScript(UUID.randomUUID().toString(), script, map);
+
+
+
+        // 创建绑定变量
+        Map<String, Object> binding = new HashMap<>();
+
+        // 创建自定义对象
+        binding.put("aNumber", 100);
+        binding.put("name", "CodeLife Leno");
+        binding.put("location", "china Guangzhou");
+
+
+        String scriptStr = """
+                "Hello, $name from $location!"
+                """;
+        System.out.println(ScriptUtil.executeScript(UUID.randomUUID().toString(), scriptStr, binding));
 
-        map.put("a", "isA");
-        map.put("b", "isB");
+        System.out.println("");
 
+        test();
 
 //        bb(sql, map);
     }
 
+
+    static void test() {
+        String scriptId = RandomUtil.randomString(10);
+        String scriptStr = """
+                "Hello, $name from $location!"
+                """;
+        String scriptId2 = RandomUtil.randomString(10);
+        String scriptStr2 = """
+                aNumber > 100
+                """;
+        String templateId = RandomUtil.randomString(10);
+        String templateStr = """
+                Hello, ${user.name}!
+                You have ${messages.size()} new messages.
+                <%// 使用 Groovy 脚本计算未读消息数 --%>
+                <% def unreadMessages = messages.count { it.startsWith("Unread") } %>
+                Unread messages000: ${unreadMessages}
+                <%// 条件判断 --%>
+                <% if (unreadMessages > 0) { %>
+                    You have some unread messages.
+                <% } else { %>
+                    All messages are read.
+                <% } %>
+                Messages:
+                <%// 遍历消息列表 --%>
+                ${messages.each { msg -> println(" -- " + msg) }}
+                """;
+
+        // 创建绑定变量
+        Map<String, Object> binding = new HashMap<>();
+
+        // 创建自定义对象
+        User user = new User("Alice");
+        binding.put("aNumber", 100);
+        binding.put("name", "CodeLife Leno");
+        binding.put("location", "china Guangzhou");
+        binding.put("user", user);
+        // 创建消息列表
+        List<String> messages = List.of("Unread Message 1", "Read Message 2", "Unread Message 3");
+        binding.put("messages", messages);
+
+        System.out.println(ScriptUtil.executeScript(scriptId, scriptStr, binding));
+        System.out.println("--------------------------------------------");
+        System.out.println(ScriptUtil.executeScript(scriptId2, scriptStr2, binding));
+        System.out.println("--------------------------------------------");
+
+        templateStr = """
+                <% if (approveSts == 03) { %>审批状态:审核中,<% } else { %>其他...,<% } %><% if (agrSts == 01) { %>额度状态:生效,<% } else if (agrSts == 02){ %>额度状态:手动冻结,<% } else if (agrSts == 02){%>额度状态:系统冻结,<% } %>
+                """;
+
+        binding.put("approveSts",3);
+        binding.put("agrSts",1);
+
+        System.out.println(TemplateUtil.execute(templateId, templateStr, binding));
+    }
+
+
+    // 自定义 User 类
+    static class User {
+        private String name;
+
+        public User(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
 }

+ 80 - 0
src/main/java/com/sundata/internalevaluation/calc/exception/CalcConfigException.java

@@ -0,0 +1,80 @@
+package com.sundata.internalevaluation.calc.exception;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-04-29 10:01:00
+ * @description: 计算单元配置异常
+ */
+public class CalcConfigException extends CalcParentException{
+
+    /**
+     * Constructs a new runtime exception with {@code null} as its
+     * detail message.  The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     */
+    public CalcConfigException() {
+        super();
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public CalcConfigException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this runtime exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A {@code null} value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public CalcConfigException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified cause and a
+     * detail message of {@code (cause==null ? null : cause.toString())}
+     * (which typically contains the class and detail message of
+     * {@code cause}).  This constructor is useful for runtime exceptions
+     * that are little more than wrappers for other throwables.
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A {@code null} value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @since 1.4
+     */
+    public CalcConfigException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Returns the detail message string of this throwable.
+     *
+     * @return the detail message string of this {@code Throwable} instance
+     * (which may be {@code null}).
+     */
+    @Override
+    public String getMessage() {
+        String message = super.getMessage();
+        String name = this.getClass().getName();
+        return message.replace(name+": ","");
+    }
+}

+ 67 - 0
src/main/java/com/sundata/internalevaluation/calc/exception/CalcParentException.java

@@ -0,0 +1,67 @@
+package com.sundata.internalevaluation.calc.exception;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-04-29 16:52:40
+ * @description: 计算单元模块总异常
+ */
+public class CalcParentException extends RuntimeException{
+
+    /**
+     * Constructs a new runtime exception with {@code null} as its
+     * detail message.  The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     */
+    public CalcParentException() {
+        super();
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public CalcParentException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this runtime exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A {@code null} value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public CalcParentException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified cause and a
+     * detail message of {@code (cause==null ? null : cause.toString())}
+     * (which typically contains the class and detail message of
+     * {@code cause}).  This constructor is useful for runtime exceptions
+     * that are little more than wrappers for other throwables.
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A {@code null} value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @since 1.4
+     */
+    public CalcParentException(Throwable cause) {
+        super(cause);
+    }
+}

+ 66 - 0
src/main/java/com/sundata/internalevaluation/calc/exception/DataException.java

@@ -0,0 +1,66 @@
+package com.sundata.internalevaluation.calc.exception;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-04-29 15:01:50
+ * @description: 数据异常
+ */
+public class DataException extends CalcParentException{
+    /**
+     * Constructs a new runtime exception with {@code null} as its
+     * detail message.  The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     */
+    public DataException() {
+        super();
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public DataException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this runtime exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A {@code null} value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public DataException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified cause and a
+     * detail message of {@code (cause==null ? null : cause.toString())}
+     * (which typically contains the class and detail message of
+     * {@code cause}).  This constructor is useful for runtime exceptions
+     * that are little more than wrappers for other throwables.
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A {@code null} value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @since 1.4
+     */
+    public DataException(Throwable cause) {
+        super(cause);
+    }
+}

+ 81 - 0
src/main/java/com/sundata/internalevaluation/calc/exception/RequestParamException.java

@@ -0,0 +1,81 @@
+package com.sundata.internalevaluation.calc.exception;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-04-29 15:03:10
+ * @description: 请求数据异常
+ */
+public class RequestParamException extends DataException{
+
+    /**
+     * Constructs a new runtime exception with {@code null} as its
+     * detail message.  The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     */
+    public RequestParamException() {
+        super();
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public RequestParamException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this runtime exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A {@code null} value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public RequestParamException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified cause and a
+     * detail message of {@code (cause==null ? null : cause.toString())}
+     * (which typically contains the class and detail message of
+     * {@code cause}).  This constructor is useful for runtime exceptions
+     * that are little more than wrappers for other throwables.
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A {@code null} value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @since 1.4
+     */
+    public RequestParamException(Throwable cause) {
+        super(cause);
+    }
+
+
+    /**
+     * Returns the detail message string of this throwable.
+     *
+     * @return the detail message string of this {@code Throwable} instance
+     * (which may be {@code null}).
+     */
+    @Override
+    public String getMessage() {
+        String message = super.getMessage();
+        String name = this.getClass().getName();
+        return message.replace(name+": ","");
+    }
+}

+ 80 - 0
src/main/java/com/sundata/internalevaluation/calc/exception/ResponseDataException.java

@@ -0,0 +1,80 @@
+package com.sundata.internalevaluation.calc.exception;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-04-29 14:50:17
+ * @description: 响应数据异常
+ */
+public class ResponseDataException extends DataException{
+
+    /**
+     * Constructs a new runtime exception with the specified cause and a
+     * detail message of {@code (cause==null ? null : cause.toString())}
+     * (which typically contains the class and detail message of
+     * {@code cause}).  This constructor is useful for runtime exceptions
+     * that are little more than wrappers for other throwables.
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A {@code null} value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @since 1.4
+     */
+    public ResponseDataException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this runtime exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A {@code null} value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public ResponseDataException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public ResponseDataException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new runtime exception with {@code null} as its
+     * detail message.  The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     */
+    public ResponseDataException() {
+        super();
+    }
+
+    /**
+     * Returns the detail message string of this throwable.
+     *
+     * @return the detail message string of this {@code Throwable} instance
+     * (which may be {@code null}).
+     */
+    @Override
+    public String getMessage() {
+        String message = super.getMessage();
+        String name = this.getClass().getName();
+        return message.replace(name+": ","");
+    }
+}

+ 79 - 0
src/main/java/com/sundata/internalevaluation/calc/exception/SendRequestException.java

@@ -0,0 +1,79 @@
+package com.sundata.internalevaluation.calc.exception;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author JoeLazy
+ * @date 2025-04-29 11:51:06
+ * @description: 接口发送请求异常
+ */
+public class SendRequestException extends CalcParentException{
+    /**
+     * Constructs a new runtime exception with {@code null} as its
+     * detail message.  The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause}.
+     */
+    public SendRequestException() {
+        super();
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message.
+     * The cause is not initialized, and may subsequently be initialized by a
+     * call to {@link #initCause}.
+     *
+     * @param message the detail message. The detail message is saved for
+     *                later retrieval by the {@link #getMessage()} method.
+     */
+    public SendRequestException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this runtime exception's detail message.
+     *
+     * @param message the detail message (which is saved for later retrieval
+     *                by the {@link #getMessage()} method).
+     * @param cause   the cause (which is saved for later retrieval by the
+     *                {@link #getCause()} method).  (A {@code null} value is
+     *                permitted, and indicates that the cause is nonexistent or
+     *                unknown.)
+     * @since 1.4
+     */
+    public SendRequestException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new runtime exception with the specified cause and a
+     * detail message of {@code (cause==null ? null : cause.toString())}
+     * (which typically contains the class and detail message of
+     * {@code cause}).  This constructor is useful for runtime exceptions
+     * that are little more than wrappers for other throwables.
+     *
+     * @param cause the cause (which is saved for later retrieval by the
+     *              {@link #getCause()} method).  (A {@code null} value is
+     *              permitted, and indicates that the cause is nonexistent or
+     *              unknown.)
+     * @since 1.4
+     */
+    public SendRequestException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Returns the detail message string of this throwable.
+     *
+     * @return the detail message string of this {@code Throwable} instance
+     * (which may be {@code null}).
+     */
+    @Override
+    public String getMessage() {
+        String message = super.getMessage();
+        String name = this.getClass().getName();
+        return message.replace(name+": ","");
+    }
+}

+ 22 - 3
src/main/java/com/sundata/internalevaluation/calc/model/CalcUnit.java

@@ -2,9 +2,12 @@ package com.sundata.internalevaluation.calc.model;
 
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.date.TimeInterval;
+import com.sundata.internalevaluation.calc.exception.*;
 import com.sundata.internalevaluation.calc.model.finals.CalcStatus;
 import com.sundata.internalevaluation.calc.model.finals.CalcType;
 import com.sundata.internalevaluation.calc.model.interfaces.Calc;
+import com.sundata.internalevaluation.calc.running.CalcRunning;
+import groovy.lang.MissingPropertyException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,9 +90,23 @@ public abstract class CalcUnit implements Calc, Serializable {
                     return this.resultContextFuture.get();
                 }
             }
-        } catch (InterruptedException | ExecutionException e) {
+        } catch (Exception e) {
+            Throwable cause = e.getCause();
             log.error(e.getMessage(), e);
-            throw new CalcException(calculateInstanceNumber, "计算出现问题,线程级别,请检查处理过程。");
+            if (cause instanceof CalcParentException calcParentException){
+                throw calcParentException;
+            }else if (cause instanceof RuntimeException runtimeException){
+                Throwable cause1 = runtimeException.getCause();
+                if (cause1 instanceof MissingPropertyException missingPropertyException){
+                    throw new RequestParamException(missingPropertyException.getMessage(),e);
+                }else{
+                    throw runtimeException;
+                }
+            } else if (e instanceof InterruptedException || e instanceof ExecutionException ) {
+                throw new CalcException(calculateInstanceNumber, "计算出现问题,线程级别,请检查处理过程。");
+            }else{
+                throw new RuntimeException(e.getMessage(),e);
+            }
         }
     }
 
@@ -120,9 +137,11 @@ public abstract class CalcUnit implements Calc, Serializable {
             setResultContext(thisResult);// 计算完成需要设置结果
             this.afterCalc(context);
         } catch (CalcException e) {
-            this.calculateInstanceNumber = null;
+            CalcRunning.getRunningList().remove(calculateInstanceNumber);
             log.error("计算失败,恢复计算逻辑: {}", calculateInstanceNumber, e);
             setStatus(CalcStatus.ERROR);
+            this.onError(calculateInstanceNumber);
+            throw e;
         }
         setStatus(CalcStatus.FINISHED);
         log.info("计算节点[{}-{}-{}]计算过程完成,耗时:{}", this.getCalcType(), this.getCalcCode(), this.getCalcName(), DateUtil.formatBetween(interval.interval()));

+ 4 - 0
src/main/java/com/sundata/internalevaluation/calc/model/interfaces/Calc.java

@@ -36,4 +36,8 @@ public interface Calc {
      * @return
      */
     void startCalc(String calculateInstanceNumber, final Map<String, Object> context, final Map<CalcUnit, CalcResult<String, Object>> sourceResults);
+
+    default void onError(String calculateInstanceNumber){
+
+    }
 }

+ 55 - 7
src/main/java/com/sundata/internalevaluation/calc/running/CalcRunning.java

@@ -1,20 +1,28 @@
 package com.sundata.internalevaluation.calc.running;
 
-import cn.hutool.core.lang.UUID;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
+import com.sundata.internalevaluation.calc.exception.CalcConfigException;
+import com.sundata.internalevaluation.calc.exception.RequestParamException;
+import com.sundata.internalevaluation.calc.exception.ResponseDataException;
+import com.sundata.internalevaluation.calc.exception.SendRequestException;
 import com.sundata.internalevaluation.calc.model.CalcResult;
 import com.sundata.internalevaluation.calc.model.CalcUnit;
 import com.sundata.internalevaluation.calc.running.threads.CalcRecursiveTask;
 import com.sundata.internalevaluation.calc.running.threads.CalcTaskResult;
 import com.sundata.internalevaluation.calc.running.threads.CalcUnitThreadFactory;
 import com.sundata.internalevaluation.calc.running.threads.fianl.CalcTaskResultType;
+import groovy.lang.MissingPropertyException;
 import org.jgrapht.Graph;
 import org.jgrapht.graph.DefaultDirectedGraph;
 import org.jgrapht.graph.DefaultEdge;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -30,6 +38,10 @@ public class CalcRunning {
      */
     private static final ConcurrentSkipListSet<String> runningList = new ConcurrentSkipListSet<>();
 
+    public static ConcurrentSkipListSet<String> getRunningList(){
+        return runningList;
+    }
+
 
     /**
      * 计算方法
@@ -40,9 +52,19 @@ public class CalcRunning {
      */
     public CalcTaskResult startCalc(String calculateInstanceNumber, CalcUnit calcUnit, Map<String, Object> context) {
 
+
+        Iterator<Map.Entry<String, Object>> iterator = context.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<String, Object> entry = iterator.next();
+            Object value = entry.getValue();
+            if (value == null || "null".equals(value)){
+                iterator.remove();
+            }
+        }
+
         // 流水号为空  生成流水号
         if (StrUtil.isEmpty(calculateInstanceNumber)) {
-            calculateInstanceNumber = UUID.randomUUID(Boolean.TRUE).toString(Boolean.TRUE);
+            calculateInstanceNumber = IdUtil.getSnowflakeNextIdStr();
         }
 
 
@@ -66,7 +88,7 @@ public class CalcRunning {
         CalcUnitThreadFactory factory = new CalcUnitThreadFactory(calculateInstanceNumber);
 
         // 创建 ForkJoinPool 并使用自定义线程工厂
-        ForkJoinPool customPool = new ForkJoinPool(4, factory, null, false);
+        ForkJoinPool customPool = new ForkJoinPool(20, factory, null, true);
 
         // ??
         final ConcurrentHashMap<String, Object> content = new ConcurrentHashMap<>(context);
@@ -82,11 +104,37 @@ public class CalcRunning {
         graphAddVertex(graph,calcUnit,calcUnit.getSourceCalcUnits());
 
         // 提交任务到自定义线程池
-        CalcRecursiveTask task = new CalcRecursiveTask(calculateInstanceNumber, calcUnit, content, graph, results,childResults);
-        CalcResult<String ,Object> resultMain = customPool.submit(task).join();
-        customPool.shutdown();
+        CalcResult<String ,Object> resultMain = null;
+        try {
+            CalcRecursiveTask task = new CalcRecursiveTask(calculateInstanceNumber, calcUnit, content, graph, results,childResults);
+            resultMain = customPool.submit(task).join();
+            resultMap.putAll(resultMain);
+        } catch (Exception e) {
+            result.setCode("500");
+            String message = e.getMessage();
+            log.error(message,e);
+            if (e instanceof CalcConfigException){
+                result.setResultType(CalcTaskResultType.ConfigProblem);
+            }else if (e instanceof SendRequestException){
+                result.setResultType(CalcTaskResultType.RequestProblem);
+            }else if (e instanceof ResponseDataException){
+                result.setResultType(CalcTaskResultType.ResponseProblem);
+            }else if (e instanceof RequestParamException || e instanceof MissingPropertyException){
+                result.setResultType(CalcTaskResultType.ParameterProblem);
+            }else{
+                result.setResultType(CalcTaskResultType.ProceduralIssues);
+                message = "程序内部异常";
+            }
+            StringWriter sw = new StringWriter();
+            e.printStackTrace(new PrintWriter(sw, true));
+            resultMap.put("errorDetailMessage",sw.toString());
+            result.setMessage(message);
+            return result;
+        } finally {
+            System.out.println("关闭计算");
+            customPool.shutdown();
+        }
         // 删除正在运行的处理过程
-        resultMap.putAll(resultMain);
         runningList.remove(calculateInstanceNumber);
         return result;
     }

+ 21 - 1
src/main/java/com/sundata/internalevaluation/calc/running/threads/CalcTaskResult.java

@@ -11,12 +11,22 @@ public class CalcTaskResult {
     private CalcTaskResultType resultType;
     private String code;
     private String result;
+    private String message;
     private Map<String ,Object> resultMap;
 
-    public CalcTaskResult(CalcTaskResultType resultType, String code, String result, Map<String, Object> resultMap) {
+    public CalcTaskResult(CalcTaskResultType resultType, String code, String message, Map<String, Object> resultMap) {
+        this.resultType = resultType;
+        this.code = code;
+        this.result = resultType.getValue();
+        this.message = message;
+        this.resultMap = resultMap;
+    }
+
+    public CalcTaskResult(CalcTaskResultType resultType, String code, String result, String message, Map<String, Object> resultMap) {
         this.resultType = resultType;
         this.code = code;
         this.result = result;
+        this.message = message;
         this.resultMap = resultMap;
     }
 
@@ -26,6 +36,7 @@ public class CalcTaskResult {
 
     public void setResultType(CalcTaskResultType resultType) {
         this.resultType = resultType;
+        this.result  = resultType.getValue();
     }
 
     public String getCode() {
@@ -44,6 +55,14 @@ public class CalcTaskResult {
         this.result = result;
     }
 
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
     public Map<String, Object> getResultMap() {
         return resultMap;
     }
@@ -58,6 +77,7 @@ public class CalcTaskResult {
                 .add("resultType=" + resultType)
                 .add("code='" + code + "'")
                 .add("result='" + result + "'")
+                .add("message='" + message + "'")
                 .add("resultMap=" + resultMap)
                 .toString();
     }

+ 1 - 1
src/main/java/com/sundata/internalevaluation/calc/running/threads/fianl/CalcTaskResultType.java

@@ -3,7 +3,7 @@ package com.sundata.internalevaluation.calc.running.threads.fianl;
 public enum CalcTaskResultType {
 
     SUCCESS("成功"),OtherFailures("其他失败"),ProceduralIssues("程序问题"),ParameterProblem("参数问题"),PerformanceIssues("性能问题")
-    ,Ignore("忽略")
+    ,Ignore("忽略"),ConfigProblem("配置问题"),RequestProblem("请求问题"),ResponseProblem("响应问题")
     ;
 
     private final String value;

+ 1 - 1
src/main/java/com/sundata/internalevaluation/calc/util/CalciteUtil.java

@@ -177,7 +177,7 @@ public class CalciteUtil {
         // 将所有列名打印输出
         List<String> columns = new ArrayList<>();
         StringJoiner sj = new StringJoiner("\t");
-        for (int i = 1; i < columnCount; i++) {
+        for (int i = 1; i <= columnCount; i++) {
             String columnName = metaData.getColumnName(i);
             columns.add(columnName);
             sj.add(columnName);

+ 6 - 1
src/main/java/com/sundata/internalevaluation/configuration/controller/RiskControlStrategyAction.java

@@ -107,7 +107,12 @@ public class RiskControlStrategyAction extends BaseAction {
         }else{
             throw new BusinessException("参数未传!!");
         }
-        CalcTaskResult calcTaskResult = CalcUtil.calcRiskCtrl("", riskCtrlModel.getRiskCtrlNo(), paramMap);
+        CalcTaskResult calcTaskResult = null;
+        try {
+            calcTaskResult = CalcUtil.calcRiskCtrl("", riskCtrlModel.getRiskCtrlNo(), paramMap);
+        } catch (Exception e) {
+            throw new BusinessException(e.getMessage(),e);
+        }
         return calcTaskResult;
     }
 

+ 4 - 6
src/main/java/com/sundata/internalevaluation/configuration/mapper/DataSourcesMapper.java

@@ -4,8 +4,6 @@ import com.sundata.internalevaluation.configuration.model.DataItemConfigModel;
 import com.sundata.internalevaluation.configuration.model.DataSourceModel;
 import com.sundata.internalevaluation.configuration.model.InputParamModel;
 import com.sundata.internalevaluation.configuration.model.QueryLogicModel;
-import org.apache.ibatis.annotations.Param;
-
 
 import java.util.List;
 
@@ -20,17 +18,17 @@ public interface DataSourcesMapper {
 
     void createData(DataSourceModel model);
 
-    void createInputParamData(@Param("inputParam") List<InputParamModel> inputParam);
+    int createInputParamData(InputParamModel inputParam);
 
-    void createDataItemConfigData(@Param("dataItemConfig") List<DataItemConfigModel> dataItemConfig);
+    int createDataItemConfigData(DataItemConfigModel dataItemConfig);
 
-    void createQueryLogicData(@Param("queryLogic") List<QueryLogicModel> queryLogic);
+    int createQueryLogicData(QueryLogicModel queryLogic);
 
     void deleteRows(DataSourceModel model);
 
     void updateExistData(DataSourceModel model);
 
-    void deleteInputParamRows();
+    void deleteInputParamRows(DataSourceModel model);
 
     void deleteDataSourceRows(DataSourceModel model);
 

+ 1 - 1
src/main/java/com/sundata/internalevaluation/configuration/mapper/IndexConfigMapper.java

@@ -27,7 +27,7 @@ public interface IndexConfigMapper {
      */
     List<IndexModel> selectIndexListByRuleNo(@Param("ruleNo") String ruleNo);
 
-    void createIndexSource(@Param("indexSource") List<IndexSourceModel> indexSource);
+    int createIndexSource(IndexSourceModel indexSourceModel);
 
     void deleteIndexSource(String indexNo);
 }

+ 0 - 8
src/main/java/com/sundata/internalevaluation/configuration/mapper/RuleMapper.java

@@ -63,14 +63,6 @@ public interface RuleMapper {
 	int deleteIndexByRuleNo(@Param("ruleNo") String ruleNo);
 
 
-	/**
-	 * 插入所有规则 指标管关联关系
-	 * @param list 集合
-	 * @return 返回影响行数
-	 */
-	int insertIndexList(@Param("list") List<RuleIndex> list);
-
-
 	/**
 	 * 插入所有规则 指标管关联关系
 	 * @param ruleIndex 实体信息

+ 3 - 3
src/main/java/com/sundata/internalevaluation/configuration/mapper/RuleSetMapper.java

@@ -1,12 +1,12 @@
 package com.sundata.internalevaluation.configuration.mapper;
 
-import java.util.List;
-
 import com.sundata.internalevaluation.configuration.model.RuleSet;
 import com.sundata.internalevaluation.configuration.model.RuleSetRule;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 @Mapper
 public interface RuleSetMapper {
 
@@ -67,7 +67,7 @@ public interface RuleSetMapper {
 	 * @param associateRules
 	 * @return
 	 */
-	int insertAssociateRule(@Param("associateRules") List<RuleSetRule> associateRules);
+	int insertAssociateRule(RuleSetRule associateRule);
 
 
 	/**

+ 10 - 0
src/main/java/com/sundata/internalevaluation/configuration/model/InputParamModel.java

@@ -9,6 +9,8 @@ public class InputParamModel {
     private String paramDescribe;
     // 参数中文名称
     private String paramCName;
+    // 数据来源编号
+    private String dataSourcesNo;
 
     public String getParamNo() {
         return paramNo;
@@ -41,4 +43,12 @@ public class InputParamModel {
     public void setParamCName(String paramCName) {
         this.paramCName = paramCName;
     }
+
+    public String getDataSourcesNo() {
+        return dataSourcesNo;
+    }
+
+    public void setDataSourcesNo(String dataSourcesNo) {
+        this.dataSourcesNo = dataSourcesNo;
+    }
 }

+ 39 - 64
src/main/java/com/sundata/internalevaluation/configuration/mybatis/DataSourcesMapper.xml

@@ -88,75 +88,50 @@
     </insert>
 
     <!-- 输入参数配置页面新增 -->
-    <insert id="createInputParamData" parameterType="java.util.List">
-        INSERT ALL
-        <foreach collection="inputParam" item="model">
-             INTO CALC_CONF_INPUTPARAM
-            (
-            PARAMNO,
-            PARAMNAME,
-            PARAMDESCRIBE,
-            PARAMCNAME
-            )
-            VALUES
-            (
-            #{model.paramNo},
-            #{model.paramName},
-            #{model.paramDescribe},
-            #{model.paramCName}
-            )
-        </foreach>
-        SELECT 1 FROM DUAL
+    <insert id="createInputParamData">
+        INSERT INTO CALC_CONF_INPUTPARAM
+        (PARAMNO,
+         PARAMNAME,
+         PARAMDESCRIBE,
+         DATASOURCESNO,
+         PARAMCNAME)
+        VALUES (#{paramNo},
+                #{paramName},
+                #{paramDescribe},
+                #{dataSourcesNo},
+                #{paramCName})
     </insert>
 
     <!-- 数据项配置页面新增 -->
-    <insert id="createDataItemConfigData" parameterType="java.util.List">
-        INSERT ALL
-        <foreach collection="dataItemConfig" item="model">
-             INTO CALC_CONF_DATAITEM
-            (
-            DATASOURCESNO,
-            DATAITEMNO,
-            DATAITEMNAME,
-            DATAITEMROUTE,
-            DATAITEMSQL
-            )
-            VALUES
-            (
-            #{model.dataSourcesNo},
-            #{model.dataItemNo},
-            #{model.dataItemName},
-            #{model.dataItemRoute},
-            #{model.dataItemSql}
-            )
-        </foreach>
-        SELECT 1 FROM DUAL
+    <insert id="createDataItemConfigData">
+        INSERT INTO CALC_CONF_DATAITEM
+        (DATASOURCESNO,
+         DATAITEMNO,
+         DATAITEMNAME,
+         DATAITEMROUTE,
+         DATAITEMSQL)
+        VALUES (#{dataSourcesNo},
+                #{dataItemNo},
+                #{dataItemName},
+                #{dataItemRoute},
+                #{dataItemSql})
     </insert>
 
     <!-- 数据来源配置页面新增 -->
-    <insert id="createQueryLogicData" parameterType="java.util.List">
-        INSERT ALL
-        <foreach collection="queryLogic" item="model">
-             INTO CALC_CONF_QUERYLOGIC
-            (
-            DATASOURCESNO,
-            QUERYLOGICNO,
-            SELECTSQLSCRIPT,
-            SCRIPTDESCRIPTION,
-            DATAITEMNAME,
-            DATAITEMCNAME
-            )
-            VALUES
-            (
-            #{model.dataSourcesNo},
-            #{model.queryLogicNo},
-            #{model.selectSqlScript},
-            #{model.scriptDescription},
-            #{model.dataItemName},
-            #{model.dataItemCName}
-            )
-        </foreach>
-        SELECT 1 FROM DUAL
+    <insert id="createQueryLogicData">
+        INSERT INTO CALC_CONF_QUERYLOGIC
+        (DATASOURCESNO,
+         QUERYLOGICNO,
+         SELECTSQLSCRIPT,
+         SCRIPTDESCRIPTION,
+         DATAITEMNAME,
+         DATAITEMCNAME)
+        VALUES (#{dataSourcesNo},
+                #{queryLogicNo},
+                #{selectSqlScript},
+                #{scriptDescription},
+                #{dataItemName},
+                #{dataItemCName})
     </insert>
 
 
@@ -172,7 +147,7 @@
 
     <!-- 数据来源配置页面删除 -->
     <delete id="deleteInputParamRows">
-        DELETE FROM CALC_CONF_INPUTPARAM
+        DELETE FROM CALC_CONF_INPUTPARAM where DATASOURCESNO = #{dataSourcesNo}
     </delete>
 
     <!-- 数据来源配置页面删除 -->

+ 12 - 21
src/main/java/com/sundata/internalevaluation/configuration/mybatis/IndexConfigMapper.xml

@@ -65,27 +65,18 @@
     </insert>
 
     <!-- 指标数据来源页面新增 -->
-    <insert id="createIndexSource" parameterType="java.util.List">
-        INSERT ALL
-        <foreach collection="indexSource" item="model">
-              INTO CALC_CONF_INDEXSOURCE
-            (
-            INDEXSOURCENO,
-            INDEXNO,
-            OTHERINDEXNO,
-            DATASETNO,
-            DATASOURCETYPE
-            )
-            VALUES
-            (
-            #{model.indexSourceNo},
-            #{model.indexNo},
-            #{model.otherIndexNo},
-            #{model.dataSetNo},
-            #{model.dataSourceType}
-            )
-        </foreach>
-        SELECT 1 FROM DUAL
+    <insert id="createIndexSource">
+        INSERT INTO CALC_CONF_INDEXSOURCE
+        (INDEXSOURCENO,
+         INDEXNO,
+         OTHERINDEXNO,
+         DATASETNO,
+         DATASOURCETYPE)
+        VALUES (#{indexSourceNo},
+                #{indexNo},
+                #{otherIndexNo},
+                #{dataSetNo},
+                #{dataSourceType})
     </insert>
 
     <!-- 指标配置页面删除 -->

+ 0 - 10
src/main/java/com/sundata/internalevaluation/configuration/mybatis/RuleMapper.xml

@@ -210,16 +210,6 @@
     </delete>
 
 
-    <!-- 插入所有规则 指标管关联关系 -->
-    <insert id="insertIndexList" parameterType="java.util.List">
-        INSERT ALL
-        <foreach collection="list" item="item">
-            into CALC_CONF_RULE_INDEX (RULE_NO,INDEX_NO,RULE_LOGIC_PARAM) values
-            (#{item.ruleNo},#{item.indexNo},#{item.ruleLogicParam})
-        </foreach>
-        SELECT 1 FROM dual
-    </insert>
-
     <insert id="insertIndex">
         insert into CALC_CONF_RULE_INDEX (RULE_NO,INDEX_NO,RULE_LOGIC_PARAM) values
             (#{ruleNo},#{indexNo},#{ruleLogicParam})

+ 3 - 8
src/main/java/com/sundata/internalevaluation/configuration/mybatis/RuleSetMapper.xml

@@ -156,14 +156,9 @@
     </delete>
 
 
-    <insert id="insertAssociateRule"
-            parameterType="java.util.List">
-        INSERT ALL
-        <foreach collection="associateRules" index="id" item="item">
-            INTO CALC_CONF_RULESET_RULE(RULE_NO, RULES_NO)
-            VALUES ( #{item.ruleNo}, #{item.rulesNo})
-        </foreach>
-        SELECT 1 FROM dual
+    <insert id="insertAssociateRule">
+        INSERT CALC_CONF_RULESET_RULE(RULE_NO, RULES_NO)
+            VALUES ( #{ruleNo}, #{rulesNo})
     </insert>
 
     <!-- 规则集生成字典 -->

+ 64 - 21
src/main/java/com/sundata/internalevaluation/configuration/service/DataSourcesService.java

@@ -33,28 +33,59 @@ public class DataSourcesService {
      * @param model 新增数据
      */
     public void createData(DataSourceModel model) {
-
         // 先插入数据来源信息
         dataSourcesMapper.createData(model);
+        // 插入输入参数信息
+        insertInputParamAndDataItemAndQueryLogic(model);
+    }
 
-        if (null != model.getInputParam() && !model.getInputParam().isEmpty()) {
-            dataSourcesMapper.createInputParamData(model.getInputParam());
+    /**
+     * 插入查询逻辑信息
+     * @param queryLogicList 输入参数列表
+     * @return 影响行数
+     */
+    public int createQueryLogicData(List<QueryLogicModel> queryLogicList){
+        if (queryLogicList == null || queryLogicList.isEmpty()){
+            return 0;
         }
-
-        if (null != model.getDataItemConfig() && !model.getDataItemConfig().isEmpty()) {
-            for (DataItemConfigModel m : model.getDataItemConfig()) {
-                m.setDataSourcesNo(model.getDataSourcesNo());
-            }
-            dataSourcesMapper.createDataItemConfigData(model.getDataItemConfig());
+        int rows = 0;
+        for (QueryLogicModel queryLogic : queryLogicList) {
+            rows += dataSourcesMapper.createQueryLogicData(queryLogic);
         }
+        return rows;
+    }
 
-        if (null != model.getQueryLogic() && !model.getQueryLogic().isEmpty()) {
-            for (QueryLogicModel m : model.getQueryLogic()) {
-                m.setDataSourcesNo(model.getDataSourcesNo());
-            }
-            dataSourcesMapper.createQueryLogicData(model.getQueryLogic());
+    /**
+     * 插入数据项信息
+     * @param dataItemList 输入参数列表
+     * @return 影响行数
+     */
+    public int createDataItemConfigData(List<DataItemConfigModel> dataItemList){
+        if (dataItemList == null || dataItemList.isEmpty()){
+            return 0;
         }
+        int rows = 0;
+        for (DataItemConfigModel dataItem : dataItemList) {
+            rows += dataSourcesMapper.createDataItemConfigData(dataItem);
+        }
+        return rows;
+    }
+
 
+    /**
+     * 插入输入参数信息
+     * @param inputParamList 输入参数列表
+     * @return 影响行数
+     */
+    public int createInputParamData(List<InputParamModel> inputParamList){
+        if (inputParamList == null || inputParamList.isEmpty()){
+            return 0;
+        }
+        int rows = 0;
+        for (InputParamModel inputParam : inputParamList) {
+            rows += dataSourcesMapper.createInputParamData(inputParam);
+        }
+        return rows;
     }
 
 
@@ -74,31 +105,43 @@ public class DataSourcesService {
      * @param model 数据实体
      */
     public void updateExistData(DataSourceModel model) {
-
         dataSourcesMapper.updateExistData(model);
-        dataSourcesMapper.deleteInputParamRows();
+        dataSourcesMapper.deleteInputParamRows(model);
         dataSourcesMapper.deleteDataSourceRows(model);
         dataSourcesMapper.deleteQueryLogicRows(model);
+        // 插入输入参数信息
+        insertInputParamAndDataItemAndQueryLogic(model);
+    }
+
+
+    /**
+     * 插入输入参数、数据项、查询逻辑等信息
+     * @param model 数据来源实体
+     */
+    public void insertInputParamAndDataItemAndQueryLogic(DataSourceModel model) {
+        // TODO 输入参数不需要关联数据源??
+//        this.createInputParamData(model.getInputParam());
 
         if (null != model.getInputParam() && !model.getInputParam().isEmpty()) {
-            dataSourcesMapper.createInputParamData(model.getInputParam());
+            for (InputParamModel m : model.getInputParam()) {
+                m.setDataSourcesNo(model.getDataSourcesNo());
+            }
+            this.createInputParamData(model.getInputParam());
         }
 
         if (null != model.getDataItemConfig() && !model.getDataItemConfig().isEmpty()) {
             for (DataItemConfigModel m : model.getDataItemConfig()) {
                 m.setDataSourcesNo(model.getDataSourcesNo());
             }
-            dataSourcesMapper.createDataItemConfigData(model.getDataItemConfig());
+            this.createDataItemConfigData(model.getDataItemConfig());
         }
 
         if (null != model.getQueryLogic() && !model.getQueryLogic().isEmpty()) {
             for (QueryLogicModel m : model.getQueryLogic()) {
                 m.setDataSourcesNo(model.getDataSourcesNo());
             }
-            dataSourcesMapper.createQueryLogicData(model.getQueryLogic());
+            this.createQueryLogicData(model.getQueryLogic());
         }
-
-
     }
 
 

+ 18 - 2
src/main/java/com/sundata/internalevaluation/configuration/service/IndexConfigService.java

@@ -43,10 +43,26 @@ public class IndexConfigService {
                 m.setIndexNo(model.getIndexNo());
                 m.setIndexSourceNo(UUID.randomUUID().toString());
             }
-            indexConfigMapper.createIndexSource(model.getIndexDataSource());
+            this.createIndexSource(model.getIndexDataSource());
         }
     }
 
+    /**
+     * 插入指标
+     * @param indexSource IndexSourceModel列表
+     * @return 影响行数
+     */
+    public int createIndexSource(List<IndexSourceModel> indexSource) {
+        if (indexSource == null || indexSource.isEmpty()) {
+            return 0;
+        }
+        int rows = 0;
+        for (IndexSourceModel indexSourceModel : indexSource) {
+            rows += indexConfigMapper.createIndexSource(indexSourceModel);
+        }
+        return rows;
+    }
+
 
     /**
      * 指标配置删除
@@ -72,7 +88,7 @@ public class IndexConfigService {
                 m.setIndexNo(model.getIndexNo());
                 m.setIndexSourceNo(UUID.randomUUID().toString());
             }
-            indexConfigMapper.createIndexSource(model.getIndexDataSource());
+            this.createIndexSource(model.getIndexDataSource());
         }else{
             indexConfigMapper.deleteIndexSource(model.getIndexNo());
         }

+ 10 - 2
src/main/java/com/sundata/internalevaluation/configuration/service/RuleSetService.java

@@ -74,7 +74,7 @@ public class RuleSetService {
             List<String> ruleIds = ruleSet.getRuleIds();
             if (ruleIds != null && !ruleIds.isEmpty()) {
                 List<RuleSetRule> associateRules = ruleIds.stream().map(ruleId -> new RuleSetRule(ruleId, rulesNo)).collect(Collectors.toList());
-                ruleSetMapper.insertAssociateRule(associateRules);
+                this.insertAssociateRule(associateRules);
             }
 
             return ruleSetMapper.insertIgnoreNull(ruleSet);
@@ -83,6 +83,14 @@ public class RuleSetService {
         }
     }
 
+    public int insertAssociateRule(List<RuleSetRule> associateRules){
+        int rows = 0;
+        for (RuleSetRule associateRule : associateRules) {
+            rows += ruleSetMapper.insertAssociateRule(associateRule);
+        }
+        return rows;
+    }
+
 
     /**
      * 修改,忽略null字段
@@ -103,7 +111,7 @@ public class RuleSetService {
         List<String> ruleIds = ruleSet.getRuleIds();
         if (ruleIds != null && !ruleIds.isEmpty()) {
             List<RuleSetRule> associateRules = ruleIds.stream().map(ruleId -> new RuleSetRule(ruleId, rulesNo)).collect(Collectors.toList());
-            ruleSetMapper.insertAssociateRule(associateRules);
+            this.insertAssociateRule(associateRules);
         }
 
         return ruleSetMapper.updateIgnoreNull(ruleSet);

+ 1 - 1
src/main/java/com/sundata/internalevaluation/script/execute/TemplateExecute.java

@@ -161,7 +161,7 @@ public class TemplateExecute {
             return template.make(params).toString();
         } catch (Exception e) {
             log.error(e.getMessage(), e);
+            throw new RuntimeException("计算失败,请检查实际执行情况与日志!",e);
         }
-        throw new RuntimeException("计算失败,请检查实际执行情况与日志!");
     }
 }