浏览代码

refact: jsEngine组件化

icetimidus 1 年之前
父节点
当前提交
b0b5c281e9

+ 6 - 31
report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasetparam/service/impl/DataSetParamServiceImpl.java

@@ -2,26 +2,22 @@ package com.anjiplus.template.gaea.business.modules.datasetparam.service.impl;
 
 import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
 import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
+import com.anjiplus.template.gaea.business.code.ResponseCode;
 import com.anjiplus.template.gaea.business.modules.datasetparam.controller.dto.DataSetParamDto;
 import com.anjiplus.template.gaea.business.modules.datasetparam.dao.DataSetParamMapper;
 import com.anjiplus.template.gaea.business.modules.datasetparam.dao.entity.DataSetParam;
 import com.anjiplus.template.gaea.business.modules.datasetparam.service.DataSetParamService;
 import com.anjiplus.template.gaea.business.modules.datasetparam.util.ParamsResolverHelper;
-import com.anjiplus.template.gaea.business.code.ResponseCode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.Sets;
-import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import com.anjiplus.template.gaea.business.util.JsEngineUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import javax.script.Invocable;
-import javax.script.ScriptEngine;
+import javax.annotation.Resource;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
 * @desc DataSetParam 数据集动态参数服务实现
@@ -32,15 +28,6 @@ import java.util.Set;
 //@RequiredArgsConstructor
 @Slf4j
 public class DataSetParamServiceImpl implements DataSetParamService {
-    static final Set<String> blackList = Sets.newHashSet("java.lang.ProcessBuilder", "java.lang.Runtime", "java.lang.ProcessImpl");
-    private static final ThreadLocal<ScriptEngine> engineHolder = ThreadLocal.withInitial(() -> {
-        NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
-        ScriptEngine engine = factory.getScriptEngine(clz -> !blackList.contains(clz));
-        return engine;
-    });
-    public static ScriptEngine getEngine() {
-        return engineHolder.get();
-    }
 
     @Autowired
     private DataSetParamMapper dataSetParamMapper;
@@ -50,6 +37,8 @@ public class DataSetParamServiceImpl implements DataSetParamService {
       return dataSetParamMapper;
     }
 
+    @Resource
+    private JsEngineUtil jsEngineUtil;
     /**
      * 参数替换
      *
@@ -101,24 +90,10 @@ public class DataSetParamServiceImpl implements DataSetParamService {
         String validationRules = dataSetParamDto.getValidationRules();
         if (StringUtils.isNotBlank(validationRules)) {
             try {
-                ScriptEngine engine = getEngine();
-                engine.eval(validationRules);
-                if(engine instanceof Invocable){
-                    Invocable invocable = (Invocable) engine;
-                    Object exec = invocable.invokeFunction("verification", dataSetParamDto);
-                    ObjectMapper objectMapper = new ObjectMapper();
-                    if (exec instanceof Boolean) {
-                        return objectMapper.convertValue(exec, Boolean.class);
-                    }else {
-                        return objectMapper.convertValue(exec, String.class);
-                    }
-
-                }
-
+                return jsEngineUtil.verification(validationRules,dataSetParamDto);
             } catch (Exception ex) {
                 throw BusinessExceptionBuilder.build(ResponseCode.EXECUTE_JS_ERROR, ex.getMessage());
             }
-
         }
         return true;
     }

+ 7 - 33
report-core/src/main/java/com/anjiplus/template/gaea/business/modules/datasettransform/service/impl/JsTransformServiceImpl.java

@@ -5,14 +5,11 @@ import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
 import com.anjiplus.template.gaea.business.code.ResponseCode;
 import com.anjiplus.template.gaea.business.modules.datasettransform.controller.dto.DataSetTransformDto;
 import com.anjiplus.template.gaea.business.modules.datasettransform.service.TransformStrategy;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import com.anjiplus.template.gaea.business.util.JsEngineUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
-import javax.script.Invocable;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import java.util.ArrayList;
+import javax.annotation.Resource;
 import java.util.List;
 
 /**
@@ -21,13 +18,6 @@ import java.util.List;
 @Component
 @Slf4j
 public class JsTransformServiceImpl implements TransformStrategy {
-
-    private ScriptEngine engine;
-    {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        engine = manager.getEngineByName("JavaScript");
-    }
-
     /**
      * 数据清洗转换 类型
      *
@@ -46,35 +36,19 @@ public class JsTransformServiceImpl implements TransformStrategy {
      */
     @Override
     public List<JSONObject> transform(DataSetTransformDto def, List<JSONObject> data) {
-        return getValueFromJs(def,data);
+        return getValueFromJs(def, data);
     }
 
+    @Resource
+    private JsEngineUtil jsEngineUtil;
+
     private List<JSONObject> getValueFromJs(DataSetTransformDto def, List<JSONObject> data) {
         String js = def.getTransformScript();
         try {
-            engine.eval(js);
-            if(engine instanceof Invocable){
-                Invocable invocable = (Invocable) engine;
-                Object dataTransform = invocable.invokeFunction("dataTransform", data);
-                if (dataTransform instanceof List) {
-                    return (List<JSONObject>) dataTransform;
-                }
-                //前端js自定义的数组[{"aa":"bb"}]解析后变成{"0":{"aa":"bb"}}
-                ScriptObjectMirror scriptObjectMirror = (ScriptObjectMirror) dataTransform;
-                List<JSONObject> result = new ArrayList<>();
-                scriptObjectMirror.forEach((key, value) -> {
-                    ScriptObjectMirror valueObject = (ScriptObjectMirror) value;
-                    JSONObject jsonObject = new JSONObject();
-                    jsonObject.putAll(valueObject);
-                    result.add(jsonObject);
-                });
-                return result;
-            }
-
+            return jsEngineUtil.eval(js, data);
         } catch (Exception ex) {
             log.info("执行js异常", ex);
             throw BusinessExceptionBuilder.build(ResponseCode.EXECUTE_JS_ERROR, ex.getMessage());
         }
-        return null;
     }
 }

+ 84 - 0
report-core/src/main/java/com/anjiplus/template/gaea/business/util/JsEngineUtil.java

@@ -0,0 +1,84 @@
+package com.anjiplus.template.gaea.business.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Sets;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import org.springframework.core.NamedInheritableThreadLocal;
+import org.springframework.stereotype.Component;
+
+import javax.script.Invocable;
+import javax.script.ScriptEngine;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+@Component
+public class JsEngineUtil {
+
+    final Set<String> blackList = Sets.newHashSet(
+            "java.lang.ProcessBuilder", "java.lang.Runtime", "java.lang.ProcessImpl");
+    ThreadLocal<ScriptEngine> engineHolder = new NamedInheritableThreadLocal<ScriptEngine>("jsEngine") {
+        @Override
+        protected ScriptEngine initialValue() {
+            NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+            return factory.getScriptEngine((clz) -> {
+                return !blackList.contains(clz);
+            });
+        }
+    };
+
+    public ScriptEngine getEngine() {
+        return engineHolder.get();
+    }
+
+    ;
+
+    private String filter(String input) {
+        //把blackList中的类替换成空字符串
+        for (String clz : blackList) {
+            input = input.replace(clz, "");
+        }
+        return input;
+    }
+
+    public List<JSONObject> eval(String js, List<JSONObject> data) throws Exception {
+        ScriptEngine engine = getEngine();
+        engine.eval(filter(js));
+        if (engine instanceof Invocable) {
+            Invocable invocable = (Invocable) engine;
+            Object dataTransform = invocable.invokeFunction("dataTransform", data);
+            if (dataTransform instanceof List) {
+                return (List<JSONObject>) dataTransform;
+            }
+            //前端js自定义的数组[{"aa":"bb"}]解析后变成{"0":{"aa":"bb"}}
+            ScriptObjectMirror scriptObjectMirror = (ScriptObjectMirror) dataTransform;
+            List<JSONObject> result = new ArrayList<>();
+            scriptObjectMirror.forEach((key, value) -> {
+                ScriptObjectMirror valueObject = (ScriptObjectMirror) value;
+                JSONObject jsonObject = new JSONObject();
+                jsonObject.putAll(valueObject);
+                result.add(jsonObject);
+            });
+            return result;
+        }
+        return null;
+    }
+
+    public Object verification(String validationRules, Object dataSetParamDto) throws Exception {
+        ScriptEngine engine = getEngine();
+        engine.eval(filter(validationRules));
+        if (engine instanceof Invocable) {
+            Invocable invocable = (Invocable) engine;
+            Object exec = invocable.invokeFunction("verification", dataSetParamDto);
+            ObjectMapper objectMapper = new ObjectMapper();
+            if (exec instanceof Boolean) {
+                return objectMapper.convertValue(exec, Boolean.class);
+            } else {
+                return objectMapper.convertValue(exec, String.class);
+            }
+        }
+        return null;
+    }
+}