From 450ed63e606df00971102937b607c7246c5904f4 Mon Sep 17 00:00:00 2001 From: clay <20932067@zju.edu.cn> Date: Tue, 23 Apr 2024 11:32:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20java=E6=89=A7=E8=A1=8C=E5=BC=95?= =?UTF-8?q?=E6=93=8E=E5=92=8Cjs=E6=89=A7=E8=A1=8C=E5=BC=95=E6=93=8E?= =?UTF-8?q?=E8=B0=83=E8=AF=95=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/common-code/pom.xml | 10 ++ .../code/console/MultiThreadedCapture.java | 45 ++++++ .../common/code/engine/JavaCodeEngine.java | 38 +++-- .../common/code/engine/JavaScriptEngine.java | 77 +++++++--- .../common/code/model/EngineResult.java | 25 ++++ .../common/decrypt/annotation/Encrypt.java | 19 +++ .../decrypt/annotation/EncryptField.java | 8 ++ .../common/decrypt/aspect/EncryptAspect.java | 136 +++++++++++++----- custom-query/custom-query-biz/pom.xml | 4 + .../query/config/RestTemplateConfig.java | 53 +++++++ .../query/constant/QueryConstant.java | 22 ++- .../controller/DataAdapterController.java | 6 +- .../query/controller/PortalController.java | 62 +++++++- .../fateverse/query/entity/DataAdapter.java | 3 + .../cn/fateverse/query/entity/Portal.java | 9 +- .../fateverse/query/entity/PortalMapping.java | 13 +- .../fateverse/query/entity/bo/PortalBo.java | 4 + .../fateverse/query/entity/dto/MockParam.java | 33 +++++ .../fateverse/query/entity/dto/PortalDto.java | 8 +- .../query/entity/query/PortalQuery.java | 4 +- .../fateverse/query/entity/vo/PortalVo.java | 21 +++ .../query/entity/vo/SimplePortalVo.java | 14 +- .../adapter/AbstractDataAdapterHandler.java | 73 ++++++++++ .../handler/adapter/DataAdapterHandler.java | 24 +++- .../impl/ExternalDataAdapterHandler.java | 73 ++++++++++ .../adapter/impl/LocalDataAdapterHandler.java | 84 +++++++---- .../handler/engine/EngineExecuteHandler.java | 4 +- .../engine/impl/JavaEngineExecuteHandler.java | 5 +- .../impl/JavaScriptEngineExecuteHandler.java | 27 +++- .../reader/DataAdapterHandlerReader.java | 21 ++- .../reader/EngineExecuteHandlerReader.java | 5 +- .../query/mapper/DataAdapterMapper.java | 8 ++ .../fateverse/query/mapper/PortalMapper.java | 24 ++++ .../query/portal/PortalDispatchServlet.java | 31 +--- .../portal/service/DispatchSyncService.java | 1 + .../service/DynamicDataSearchService.java | 4 +- .../query/service/PortalService.java | 41 ++++++ .../query/service/impl/PortalServiceImpl.java | 123 ++++++++++------ .../resources/mapper/DataAdapterMapper.xml | 25 +++- .../main/resources/mapper/PortalMapper.xml | 38 ++++- .../resources/mapper/PortalMappingMapper.xml | 7 +- .../cn/fateverse/query/ConsoleCapture.java | 32 +++++ .../java/cn/fateverse/query/DataAdapter.java | 14 -- .../cn/fateverse/query/DataAdapter1100.java | 16 +++ .../fateverse/query/JavaScriptParamTest.java | 77 ++++++++++ .../cn/fateverse/query/JavaScriptTest.java | 122 ++++++++++++++++ .../test/java/cn/fateverse/query/Main.java | 38 +++++ .../java/cn/fateverse/query/SystemOut.java | 45 ++++++ visual/pom.xml | 4 +- .../workflow/process/TriggerService.java | 8 +- 50 files changed, 1353 insertions(+), 235 deletions(-) create mode 100644 common/common-code/src/main/java/cn/fateverse/common/code/console/MultiThreadedCapture.java create mode 100644 common/common-code/src/main/java/cn/fateverse/common/code/model/EngineResult.java create mode 100644 custom-query/custom-query-biz/src/main/java/cn/fateverse/query/config/RestTemplateConfig.java create mode 100644 custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/MockParam.java create mode 100644 custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/AbstractDataAdapterHandler.java create mode 100644 custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/ExternalDataAdapterHandler.java create mode 100644 custom-query/custom-query-biz/src/test/java/cn/fateverse/query/ConsoleCapture.java delete mode 100644 custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter.java create mode 100644 custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter1100.java create mode 100644 custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptParamTest.java create mode 100644 custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptTest.java create mode 100644 custom-query/custom-query-biz/src/test/java/cn/fateverse/query/Main.java create mode 100644 custom-query/custom-query-biz/src/test/java/cn/fateverse/query/SystemOut.java diff --git a/common/common-code/pom.xml b/common/common-code/pom.xml index 9dea91f..6daff0a 100644 --- a/common/common-code/pom.xml +++ b/common/common-code/pom.xml @@ -21,6 +21,16 @@ cn.fateverse common-core + + org.graalvm.js + js-scriptengine + 22.1.0 + + + org.graalvm.js + js + 22.1.0 + \ No newline at end of file diff --git a/common/common-code/src/main/java/cn/fateverse/common/code/console/MultiThreadedCapture.java b/common/common-code/src/main/java/cn/fateverse/common/code/console/MultiThreadedCapture.java new file mode 100644 index 0000000..a0f4ddf --- /dev/null +++ b/common/common-code/src/main/java/cn/fateverse/common/code/console/MultiThreadedCapture.java @@ -0,0 +1,45 @@ +package cn.fateverse.common.code.console; + +import cn.fateverse.common.code.model.EngineResult; +import cn.fateverse.common.core.exception.CustomException; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.*; + +/** + * @author Clay + * @date 2024/4/22 17:08 + */ +public class MultiThreadedCapture { + + + private final static ExecutorService executor = Executors.newFixedThreadPool(2); + + + public static EngineResult capture(Task task) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream oldOut = System.out; + System.setOut(new PrintStream(baos)); + Object result; + String capturedOutput; + try { + result = task.execute(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + System.setOut(oldOut); + // 从捕获的字节数组输出流中获取打印的文本 + capturedOutput = baos.toString(); + } + return new EngineResult(result, capturedOutput); + } + + + public interface Task { + Object execute() throws Exception; + } + + +} diff --git a/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaCodeEngine.java b/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaCodeEngine.java index 180e34e..b15fa60 100644 --- a/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaCodeEngine.java +++ b/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaCodeEngine.java @@ -2,18 +2,21 @@ package cn.fateverse.common.code.engine; import cn.fateverse.common.code.config.JavaCodeProperties; +import cn.fateverse.common.code.console.MultiThreadedCapture; import cn.fateverse.common.code.exception.SandboxClassNotFoundException; import cn.fateverse.common.code.lock.SegmentLock; +import cn.fateverse.common.code.model.EngineResult; import cn.fateverse.common.code.sandbox.SandboxClassLoader; import cn.fateverse.common.code.sandbox.SandboxSecurityManager; +import cn.fateverse.common.core.exception.CustomException; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.springframework.util.ObjectUtils; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; @@ -73,7 +76,7 @@ public class JavaCodeEngine { * @param development 是否为开发环境 开发环境下会将生成的类在执行完成后删除,不是生产环境则会缓存提高运行效率 * @return 执行结果 */ - public T execute(String code, String className, String methodName, Class[] paramClass, Object[] args, boolean development) { + public EngineResult execute(String code, String className, String methodName, Class[] paramClass, Object[] args, boolean development) { if (development) { return developmentExecute(code, className, methodName, paramClass, args); } else { @@ -90,11 +93,10 @@ public class JavaCodeEngine { * @param methodName 方法名 * @param paramClass 参数类型数组 * @param args 参数数组 - * @param 接收泛型 * @return 执行结构 */ @SneakyThrows - private T developmentExecute(String code, String className, String methodName, Class[] paramClass, Object[] args) { + private EngineResult developmentExecute(String code, String className, String methodName, Class[] paramClass, Object[] args) { Class loadClass = null; try { // 加锁,确保类只加载一次 @@ -123,7 +125,8 @@ public class JavaCodeEngine { // 设置安全检查器 System.setSecurityManager(securityManager); // 执行方法并返回结果 - return (T) method.invoke(null, args); + return MultiThreadedCapture.capture(() -> method.invoke(null, args)); + } finally { // 从缓存中移除编译好的类 classCache.remove(className); @@ -155,10 +158,9 @@ public class JavaCodeEngine { * @param methodName 方法名 * @param paramClass 参数类型数组 * @param args 参数数组 - * @param 接收泛型 * @return 执行结构 */ - private T onlineExecute(String code, String className, String methodName, Class[] paramClass, Object[] args) { + private EngineResult onlineExecute(String code, String className, String methodName, Class[] paramClass, Object[] args) { try { Class loadClass = null; loadClass = classCache.get(className); @@ -166,7 +168,8 @@ public class JavaCodeEngine { loadClass = getLoadClass(code, className); Method method = loadClass.getMethod(methodName, paramClass); System.setSecurityManager(securityManager); - return (T) method.invoke(null, args); + Object result = (Object) method.invoke(null, args); + return new EngineResult(result); } } catch (Exception e) { e.printStackTrace(); @@ -215,22 +218,31 @@ public class JavaCodeEngine { * @return 编译完成的类对象 */ private Class compilerClass(String className, String code, URLClassLoader classLoader) { - log.info(code); File tempFile = new File(CLASS_PATH + className + JAVA_SUFFIX); try (FileWriter writer = new FileWriter(tempFile)) { writer.write(code); writer.close(); + ByteArrayOutputStream errorStream = new ByteArrayOutputStream(10240); // 编译.java文件 - compiler.run(null, null, null, tempFile.getPath()); + compiler.run(null, null, errorStream, tempFile.getPath()); + String trace = errorStream.toString();//存放控制台输出的字符串 + if (!ObjectUtils.isEmpty(trace)) { + trace = trace.replace(CLASS_PATH + className + ".", ""); + throw new CustomException("编译错误: " + trace); + } return classLoader.loadClass(className); } catch (Exception e) { e.printStackTrace(); - throw new RuntimeException(e); + if (e instanceof CustomException) { + throw (CustomException) e; + } + throw new CustomException("执行或者编辑错误!"); } } /** * 删除类 + * * @param className 删除类 * @return 删除结果 */ diff --git a/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaScriptEngine.java b/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaScriptEngine.java index 085390d..c54dc58 100644 --- a/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaScriptEngine.java +++ b/common/common-code/src/main/java/cn/fateverse/common/code/engine/JavaScriptEngine.java @@ -1,9 +1,17 @@ package cn.fateverse.common.code.engine; -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; +import cn.fateverse.common.code.console.MultiThreadedCapture; +import cn.fateverse.common.code.lock.SegmentLock; +import cn.fateverse.common.code.model.EngineResult; +import cn.fateverse.common.core.exception.CustomException; +import com.alibaba.fastjson2.JSON; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; +import org.springframework.security.core.parameters.P; + +import javax.script.*; +import java.util.HashMap; +import java.util.Map; /** * js 工具类 @@ -13,25 +21,60 @@ import javax.script.ScriptException; */ public class JavaScriptEngine { + + // 创建 GraalVM 上下文 + private static final Context context = Context.newBuilder() + .allowAllAccess(true) +// .allowHostClassLoading(true) +// .allowIO(true) +// .allowNativeAccess(true) + .build(); + + + private static final Map functionMap = new HashMap<>(); + + /** * 执行js代码 - * @param script js脚本 - * @param function js函数名 - * @param args 参数 + * + * @param script js脚本 + * @param functionName js函数名 + * @param args 参数 * @return 返回结构 - * @param 泛型类型 */ - public static T executeScript(String script, String function, Object... args) { - ScriptEngineManager manager = new ScriptEngineManager(); - ScriptEngine engine = manager.getEngineByName("JavaScript"); - try { - engine.eval(script); - Invocable inv = (Invocable) engine; - return (T) inv.invokeFunction(function, args); - } catch (ScriptException | NoSuchMethodException e) { - throw new RuntimeException(e); + public static EngineResult execute(String script, String functionName, boolean development, Object args) { + if (development) { + return MultiThreadedCapture.capture(() -> { + Context context = Context.newBuilder() + .allowAllAccess(true) + .allowHostClassLoading(true) + .allowIO(true) + .allowNativeAccess(true).build(); + context.eval("js", script); + Value executeFunction = context.getBindings("js").getMember(functionName); + Value javaObjectAsValue = Value.asValue(args); + Value result = executeFunction.execute(javaObjectAsValue); + return result.as(Object.class); + }); + } else { + Value executeFunction = getFunction(functionName, script); + Value result = executeFunction.execute(JSON.toJSONString(args)); + return new EngineResult(result.as(Object.class)); } } + private static Value getFunction(String functionName, String script) { + return SegmentLock.lock(functionName, () -> { + if (functionMap.containsKey(functionName)) { + return functionMap.get(functionName); + } + context.eval("js", script); + Value executeFunction = context.getBindings("js").getMember(functionName); + functionMap.put(functionName, executeFunction); + return executeFunction; + }); + } + + } diff --git a/common/common-code/src/main/java/cn/fateverse/common/code/model/EngineResult.java b/common/common-code/src/main/java/cn/fateverse/common/code/model/EngineResult.java new file mode 100644 index 0000000..c3580af --- /dev/null +++ b/common/common-code/src/main/java/cn/fateverse/common/code/model/EngineResult.java @@ -0,0 +1,25 @@ +package cn.fateverse.common.code.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author Clay + * @date 2024/4/22 17:10 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class EngineResult { + + private Object result; + + + private String console; + + + public EngineResult(Object result) { + this.result = result; + } +} diff --git a/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/Encrypt.java b/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/Encrypt.java index a378b65..9f2daf5 100644 --- a/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/Encrypt.java +++ b/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/Encrypt.java @@ -12,4 +12,23 @@ import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Encrypt { + + Position value() default Position.ALL; + + + EncryptType type() default EncryptType.SM4; + + + enum EncryptType { + + SM4, + + } + + enum Position { + ALL, + OUT, + IN + } + } diff --git a/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/EncryptField.java b/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/EncryptField.java index d3d5582..f361306 100644 --- a/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/EncryptField.java +++ b/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/annotation/EncryptField.java @@ -11,4 +11,12 @@ import java.lang.annotation.Target; @Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface EncryptField { + + Position value() default Position.ALL; + + enum Position { + ALL, + OUT, + IN + } } \ No newline at end of file diff --git a/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/aspect/EncryptAspect.java b/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/aspect/EncryptAspect.java index e72f998..73152dc 100644 --- a/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/aspect/EncryptAspect.java +++ b/common/common-decrypt/src/main/java/cn/fateverse/common/decrypt/aspect/EncryptAspect.java @@ -2,6 +2,7 @@ package cn.fateverse.common.decrypt.aspect; import cn.fateverse.common.core.exception.CustomException; import cn.fateverse.common.core.result.Result; +import cn.fateverse.common.decrypt.annotation.Encrypt; import cn.fateverse.common.decrypt.annotation.EncryptField; import cn.fateverse.common.decrypt.service.EncryptService; import lombok.extern.slf4j.Slf4j; @@ -11,12 +12,10 @@ import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.util.ReflectionUtils; -import javax.annotation.Resource; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Parameter; -import java.util.Collection; -import java.util.List; +import java.util.*; @Slf4j @Aspect @@ -41,36 +40,35 @@ public class EncryptAspect { @Around("@annotation(cn.fateverse.common.decrypt.annotation.Encrypt)") public Object decryptField(ProceedingJoinPoint point) throws Throwable { MethodSignature signature = (MethodSignature) point.getSignature(); - //获取请求参数 - Object[] args = point.getArgs(); //获取方法 Method method = signature.getMethod(); - //获取方法参数 Parameter对象集 参数修饰符、参数名、注解及注解类型 - Parameter[] parameters = method.getParameters(); - for (int i = 0; i < parameters.length; i++) { - Parameter parameter = parameters[i]; - //获取参数注解 - EncryptField encryptField = parameter.getAnnotation(EncryptField.class); - Object arg = args[i]; - if (null != encryptField) { - if (arg instanceof String) { - String decrypt = encryptService.decrypt((String) arg); - args[i] = decrypt; - } else if (arg instanceof List) { - try { - List list = (List) arg; - list.replaceAll(encryptService::decrypt); - args[i] = list; - } catch (Exception e) { - throw new CustomException("接受参数类型错误,请使用String类型的泛型参数"); - } - } - } else if (parameter.getType().getName().startsWith(BASE_PACKAGE)) { //返回一个类对象,该类对象标识此参数对象表示的参数的声明类型 - decrypt(arg); - } + Encrypt encrypt = method.getAnnotation(Encrypt.class); + if (encrypt == null) { + return point.proceed(); + } + //获取请求参数 + Object[] args = point.getArgs(); + if (Encrypt.Position.ALL.equals(encrypt.value()) || Encrypt.Position.IN.equals(encrypt.value())) { + decryptParams(args, method); } //正常执行业务,最后返回的返回值为Result Object proceed = point.proceed(args); + if (Encrypt.Position.ALL.equals(encrypt.value()) || Encrypt.Position.OUT.equals(encrypt.value())) { + Result error = encryptResult(proceed); + if (error != null) { + return error; + } + } + return proceed; + } + + /** + * 加密返回值 + * + * @param proceed 返回执 + * @return 加密结果 + */ + private Result encryptResult(Object proceed) { if (proceed instanceof Result) { Result result = (Result) proceed; Object data = result.getData(); @@ -91,29 +89,71 @@ public class EncryptAspect { return Result.error("加密异常!"); } } - return proceed; + return null; } + /** + * 解密参数 + * + * @param args 参数 + * @param method 方法 + * @throws Exception 异常 + */ + private void decryptParams(Object[] args, Method method) throws Exception { + //获取方法参数 Parameter对象集 参数修饰符、参数名、注解及注解类型 + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + Parameter parameter = parameters[i]; + //获取参数注解 + EncryptField encryptField = parameter.getAnnotation(EncryptField.class); + Object arg = args[i]; + if (null != encryptField) { + if (arg instanceof String) { + String decrypt = encryptService.decrypt((String) arg); + args[i] = decrypt; + } else if (arg instanceof List) { + try { + List list = (List) arg; + list.replaceAll(encryptService::decrypt); + args[i] = list; + } catch (Exception e) { + throw new CustomException("接受参数类型错误,请使用String类型的泛型参数"); + } + } + } else if (parameter.getType().getName().startsWith(BASE_PACKAGE)) { + //返回一个类对象,该类对象标识此参数对象表示的参数的声明类型 + decrypt(arg); + } + } + } - private void encrypt(Object data) throws Exception { + /** + * 加密 + * + * @param data 数据 + */ + private void encrypt(Object data) { if (data == null) { return; } Class argClass = data.getClass(); + List fieldList = new ArrayList<>(); if (argClass.getTypeName().startsWith(BASE_PACKAGE)) { - Field[] fields = argClass.getDeclaredFields(); - for (Field field : fields) { + getFields(argClass, fieldList); + for (Field field : fieldList) { EncryptField encryptField = field.getAnnotation(EncryptField.class); field.setAccessible(true); Object value = ReflectionUtils.getField(field, data); if (null == value) { continue; } - if (null != encryptField && value instanceof String) { + if (null != encryptField && value instanceof String + && (EncryptField.Position.ALL.equals(encryptField.value()) + || EncryptField.Position.IN.equals(encryptField.value()))) { String decrypt = encryptService.encrypt((String) value); ReflectionUtils.setField(field, data, decrypt); } else if (field.getType().getName().startsWith(BASE_PACKAGE)) { - if (!value.getClass().isEnum()){ + if (!value.getClass().isEnum()) { encrypt(value); } } else if (value instanceof Collection) { @@ -128,29 +168,49 @@ public class EncryptAspect { for (Object item : collection) { encrypt(item); } + } else if (data instanceof Map) { + Map map = (Map) data; + for (Object key : map.keySet()) { + Object value = map.get(key); + encrypt(key); + encrypt(value); + } } } private void decrypt(Object arg) throws Exception { Class argClass = arg.getClass(); - Field[] fields = argClass.getDeclaredFields(); - for (Field field : fields) { + List fieldList = new ArrayList<>(); + getFields(argClass, fieldList); + for (Field field : fieldList) { EncryptField encryptField = field.getAnnotation(EncryptField.class); field.setAccessible(true); Object value = ReflectionUtils.getField(field, arg); if (null == value) { continue; } - if (null != encryptField && value instanceof String) { + if (null != encryptField && value instanceof String + && (EncryptField.Position.ALL.equals(encryptField.value()) + || EncryptField.Position.OUT.equals(encryptField.value()))) { String decrypt = encryptService.decrypt((String) value); ReflectionUtils.setField(field, arg, decrypt); } else if (field.getType().getName().startsWith(BASE_PACKAGE)) { - if (!value.getClass().isEnum()){ + if (!value.getClass().isEnum()) { decrypt(value); } } } } + + private void getFields(Class argClass, List fieldList) { + if (argClass.getTypeName().startsWith(BASE_PACKAGE)) { + Field[] fields = argClass.getDeclaredFields(); + fieldList.addAll(Arrays.asList(fields)); + getFields(argClass.getSuperclass(), fieldList); + } + } + + } diff --git a/custom-query/custom-query-biz/pom.xml b/custom-query/custom-query-biz/pom.xml index f037425..4e393cf 100644 --- a/custom-query/custom-query-biz/pom.xml +++ b/custom-query/custom-query-biz/pom.xml @@ -76,6 +76,10 @@ cn.fateverse common-excel + + com.squareup.okhttp3 + okhttp + ${project.artifactId} diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/config/RestTemplateConfig.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/config/RestTemplateConfig.java new file mode 100644 index 0000000..3513760 --- /dev/null +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/config/RestTemplateConfig.java @@ -0,0 +1,53 @@ +package cn.fateverse.query.config; + +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +import java.util.concurrent.TimeUnit; + +/** + * @author Clay + * @date 2024/4/22 10:28 + */ +@Configuration +public class RestTemplateConfig { + + + @Bean + public RestTemplate httpRestTemplate() { + ClientHttpRequestFactory factory = httpRequestFactory(); + RestTemplate restTemplate = new RestTemplate(factory); + // 可以添加消息转换 + //restTemplate.setMessageConverters(...); + // 可以增加拦截器 + //restTemplate.setInterceptors(...); + return restTemplate; + } + + public ClientHttpRequestFactory httpRequestFactory() { + return new OkHttp3ClientHttpRequestFactory(okHttpConfigClient()); + } + + public OkHttpClient okHttpConfigClient() { + return new OkHttpClient().newBuilder() + .connectionPool(pool()) + .connectTimeout(1, TimeUnit.SECONDS) + .readTimeout(3, TimeUnit.SECONDS) + .writeTimeout(3, TimeUnit.SECONDS) + .hostnameVerifier((hostname, session) -> true) + // 设置代理 +// .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888))) + // 拦截器 +// .addInterceptor() + .build(); + } + + public ConnectionPool pool() { + return new ConnectionPool(2000, 300, TimeUnit.SECONDS); + } +} diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/constant/QueryConstant.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/constant/QueryConstant.java index 8c07ad9..efd8172 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/constant/QueryConstant.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/constant/QueryConstant.java @@ -6,9 +6,29 @@ package cn.fateverse.query.constant; */ public class QueryConstant { - + /** + * 自定义查询权限前缀 + */ public static final String PERMISSIONS_KEY = "custom:query:online:"; + /** + * 自定义接口Redis前缀key + */ public static final String PORTAL_KEY = "custom:query:portal:"; + /** + * 接口开发状态 + */ + public static final Integer PORTAL_DEV = 0; + + /** + * 接口发布状态 + */ + public static final Integer PORTAL_PUBLISH = 1; + + /** + * 接口内部使用 + */ + public static final Integer PORTAL_INWARD = 2; + } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/DataAdapterController.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/DataAdapterController.java index f0a9cfd..b7c776b 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/DataAdapterController.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/DataAdapterController.java @@ -66,13 +66,11 @@ public class DataAdapterController { } @ApiOperation("获取数据源适配器详细信息") - @Encrypt @GetMapping("/{adapterId}") @PreAuthorize("@ss.hasPermission('query:adapter:info')") - public Result info(@PathVariable @EncryptField String adapterId) { + public Result info(@PathVariable Long adapterId) { ObjectUtils.checkPk(adapterId); - Long id = Long.valueOf(adapterId); - DataAdapterVo dataAdapter = dataAdapterService.searchById(id); + DataAdapterVo dataAdapter = dataAdapterService.searchById(adapterId); return Result.ok(dataAdapter); } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java index cac86e4..0e50a59 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/controller/PortalController.java @@ -5,6 +5,7 @@ import cn.fateverse.common.core.result.page.TableDataInfo; import cn.fateverse.common.core.utils.ObjectUtils; import cn.fateverse.common.decrypt.annotation.Encrypt; import cn.fateverse.common.decrypt.annotation.EncryptField; +import cn.fateverse.query.entity.dto.MockParam; import cn.fateverse.query.entity.dto.PortalDto; import cn.fateverse.query.entity.query.PortalQuery; import cn.fateverse.query.entity.vo.PortalIdWrapper; @@ -36,7 +37,7 @@ public class PortalController { } @ApiOperation("获取接口管理表详细信息") - @Encrypt + @Encrypt(Encrypt.Position.IN) @GetMapping("/{portalId}") @PreAuthorize("@ss.hasPermission('query:portal:info')") public Result info(@PathVariable @EncryptField String portalId) { @@ -47,6 +48,17 @@ public class PortalController { } + @ApiOperation("详情接口") + @Encrypt(Encrypt.Position.IN) + @GetMapping("/detail/{portalId}") + public Result detail(@PathVariable @EncryptField String portalId) { + ObjectUtils.checkPk(portalId); + Long value = Long.valueOf(portalId); + PortalVo portal = portalService.searchDetailById(value); + return Result.ok(portal); + } + + @ApiOperation("获取接口管理表列表") @GetMapping @Encrypt @@ -57,7 +69,7 @@ public class PortalController { } @ApiOperation("新增接口") - @Encrypt + @Encrypt(Encrypt.Position.OUT) @PostMapping @PreAuthorize("@ss.hasPermission('query:portal:add')") public Result add(@RequestBody @Validated PortalDto portalDto) { @@ -66,7 +78,7 @@ public class PortalController { } @ApiOperation("修改接口") - @Encrypt + @Encrypt(Encrypt.Position.OUT) @PutMapping @PreAuthorize("@ss.hasPermission('query:portal:edit')") public Result edit(@RequestBody @Validated PortalDto portalDto) { @@ -76,4 +88,48 @@ public class PortalController { } + @ApiOperation("模拟执行") + @PostMapping("/mock/execute") + @PreAuthorize("@ss.hasPermission('query:portal:execute')") + public Result mockExecute(@RequestBody @Validated MockParam mockParam) { + if (ObjectUtils.isEmpty(mockParam.getCode())) { + return Result.error("代码不能为空"); + } + Object result = portalService.mockExecute(mockParam); + return Result.ok(result); + } + + @ApiOperation("获取接口数据") + @PostMapping("/mock/data") + @PreAuthorize("@ss.hasPermission('query:portal:data')") + public Result mockData(@RequestBody @Validated MockParam mockParam) { + Object result = portalService.mockData(mockParam); + return Result.ok(result); + } + + + @ApiOperation("撤销发布") + @Encrypt + @PutMapping("/cancel/{portalId}") + @PreAuthorize("@ss.hasPermission('query:portal:edit')") + public Result cancel(@PathVariable @EncryptField String portalId) { + ObjectUtils.checkPk(portalId); + Long value = Long.valueOf(portalId); + portalService.cancel(value); + return Result.ok(); + } + + + @ApiOperation("删除接口") + @Encrypt + @DeleteMapping("/{portalId}") + @PreAuthorize("@ss.hasPermission('query:portal:remove')") + public Result remove(@PathVariable @EncryptField String portalId) { + ObjectUtils.checkPk(portalId); + Long value = Long.valueOf(portalId); + portalService.delete(value); + return Result.ok(); + } + + } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/DataAdapter.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/DataAdapter.java index 6b3c62c..a4419b4 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/DataAdapter.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/DataAdapter.java @@ -78,6 +78,9 @@ public class DataAdapter extends BaseEntity { "}\n"; } else if (DataAdapterType.JAVA_SCRIPT.equals(type)) { //JavaScript代码初始化 + this.code = "function execute(data) {\n" + + "\n" + + "}"; } } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/Portal.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/Portal.java index 87a7cbd..d71f3db 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/Portal.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/Portal.java @@ -58,9 +58,16 @@ public class Portal extends BaseEntity { */ private String requestMethod; - + /** + * 是否创建数据适配器 + */ private Boolean createDataAdapter; + /** + * 是否分页 + */ + private Boolean page; + /** * 系统暴露地址 */ diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/PortalMapping.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/PortalMapping.java index d5cb4cc..e97e18c 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/PortalMapping.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/PortalMapping.java @@ -43,12 +43,23 @@ public class PortalMapping { * 映射值 自定义查询映射值为查询条件的id 第三方接口则为接口查询的key */ private String mappingValue; + /** + * 输入类型 + */ + private String inputType; + + /** + * 描述 + */ + private String description; public Boolean check() { if (ObjectUtils.isEmpty(mappingKey) || ObjectUtils.isEmpty(mappingValue) - || ObjectUtils.isEmpty(mappingType)){ + || ObjectUtils.isEmpty(mappingType) +// || ObjectUtils.isEmpty(inputType) + ) { return Boolean.FALSE; } return Boolean.TRUE; diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/bo/PortalBo.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/bo/PortalBo.java index b70e1b6..6627664 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/bo/PortalBo.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/bo/PortalBo.java @@ -25,6 +25,8 @@ public class PortalBo implements Serializable { private Long adapterId; private PortalEnum type; private String requestMethod; + private Boolean createDataAdapter; + private Boolean page; private String path; private String url; private Integer state; @@ -37,6 +39,8 @@ public class PortalBo implements Serializable { .adapterId(portal.getAdapterId()) .type(portal.getType()) .requestMethod(portal.getRequestMethod()) + .createDataAdapter(portal.getCreateDataAdapter()) + .page(portal.getPage()) .path(portal.getPath()) .url(portal.getUrl()) .state(portal.getState()) diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/MockParam.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/MockParam.java new file mode 100644 index 0000000..0cadc5b --- /dev/null +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/MockParam.java @@ -0,0 +1,33 @@ +package cn.fateverse.query.entity.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author Clay + * @date 2024/4/21 19:07 + */ +@Data +public class MockParam { + + @NotNull(message = "id不能为空") + private Long portalId; + + private String code; + + private Integer pageSize; + + private Integer pageNum; + + private List params; + + @Data + public static class Param { + + private String key; + + private Object value; + } +} diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/PortalDto.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/PortalDto.java index f110fd6..864cd8c 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/PortalDto.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/dto/PortalDto.java @@ -70,6 +70,11 @@ public class PortalDto { @NotNull(message = "是否创建数据适配器不能为空!") private Boolean createDataAdapter; + /** + * 是否分页 + */ + private Boolean page; + /** * 系统暴露地址 */ @@ -113,6 +118,7 @@ public class PortalDto { .anonymity(anonymity) .createDataAdapter(createDataAdapter) .requestMethod(requestMethod) + .page(page) .type(type) .path(path) .url(url) @@ -120,7 +126,7 @@ public class PortalDto { .build(); try { RequestMethod.valueOf(requestMethod); - }catch (Exception e){ + } catch (Exception e) { throw new RuntimeException("请求类型不支持!"); } if (!ObjectUtils.isEmpty(portalId)) { diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/query/PortalQuery.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/query/PortalQuery.java index 41b6a27..5d5465b 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/query/PortalQuery.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/query/PortalQuery.java @@ -1,4 +1,4 @@ -package cn.fateverse.query.entity.query; +package cn.fateverse.query.entity.query; import cn.fateverse.query.enums.PortalEnum; import io.swagger.annotations.ApiModel; @@ -42,4 +42,6 @@ public class PortalQuery { */ @ApiModelProperty("系统暴露地址") private String path; + + private Integer state; } \ No newline at end of file diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/PortalVo.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/PortalVo.java index f514e5c..4b94fcb 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/PortalVo.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/PortalVo.java @@ -2,6 +2,7 @@ package cn.fateverse.query.entity.vo; import cn.fateverse.query.entity.Portal; import cn.fateverse.query.entity.PortalMapping; +import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.annotations.ApiModel; import lombok.Data; import org.springframework.beans.BeanUtils; @@ -20,12 +21,32 @@ import java.util.List; @ApiModel("接口详细管理表Vo") public class PortalVo extends SimplePortalVo { + /** + * 查询类型 + */ private Integer queryType; + /** + * 是否创建数据适配器 + */ private Boolean createDataAdapter; + /** + * 是否分页 + */ + private Boolean page; + + /** + * 条件映射 + */ private List mappings; + /** + * 数据适配器信息 + */ + @JsonInclude(JsonInclude.Include.NON_NULL) + private DataAdapterVo dataAdapter; + public static PortalVo toPortalVo(Portal portal) { return toPortalVo(portal, null); } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/SimplePortalVo.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/SimplePortalVo.java index 2df83c3..9131023 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/SimplePortalVo.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/entity/vo/SimplePortalVo.java @@ -37,16 +37,14 @@ public class SimplePortalVo { * 自定义查询id */ @ApiModelProperty("自定义查询id") - @EncryptField - private String queryId; + private Long queryId; /** * 数据适配器id */ @ApiModelProperty("数据适配器id") - @EncryptField - private String adapterId; + private Long adapterId; /** * 接口名称 @@ -127,6 +125,8 @@ public class SimplePortalVo { .portalId(String.valueOf(portal.getPortalId())) .portalName(portal.getPortalName()) .anonymity(portal.getAnonymity()) + .queryId(portal.getQueryId()) + .adapterId(portal.getAdapterId()) .type(portal.getType()) .path(portal.getPath()) .state(portal.getState()) @@ -136,12 +136,6 @@ public class SimplePortalVo { .build(); portalVo.setCreateTime(portal.getCreateTime()); portalVo.setUpdateTime(portal.getUpdateTime()); - if (!ObjectUtils.isEmpty(portal.getQueryId())) { - portalVo.setQueryId(String.valueOf(portal.getQueryId())); - } - if (!ObjectUtils.isEmpty(portal.getAdapterId())) { - portalVo.setAdapterId(String.valueOf(portal.getAdapterId())); - } return portalVo; } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/AbstractDataAdapterHandler.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/AbstractDataAdapterHandler.java new file mode 100644 index 0000000..269d7f8 --- /dev/null +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/AbstractDataAdapterHandler.java @@ -0,0 +1,73 @@ +package cn.fateverse.query.handler.adapter; + +import cn.fateverse.common.code.model.EngineResult; +import cn.fateverse.query.entity.DataAdapter; +import cn.fateverse.query.handler.reader.EngineExecuteHandlerReader; +import cn.fateverse.query.mapper.DataAdapterMapper; +import org.springframework.util.ObjectUtils; + +/** + * @author Clay + * @date 2024/4/19 22:44 + */ +public abstract class AbstractDataAdapterHandler implements DataAdapterHandler { + + protected final DataAdapterMapper dataAdapterMapper; + + + protected final EngineExecuteHandlerReader handlerReader; + + + protected AbstractDataAdapterHandler(DataAdapterMapper dataAdapterMapper, EngineExecuteHandlerReader handlerReader) { + this.dataAdapterMapper = dataAdapterMapper; + this.handlerReader = handlerReader; + } + + protected Object execute(Long adapterId, Object data, boolean development) { + if (ObjectUtils.isEmpty(adapterId)) { + return data; + } + //获取当当前接口对应的数据适配器 + DataAdapter dataAdapter = dataAdapterMapper.selectById(adapterId); + if (ObjectUtils.isEmpty(dataAdapter)) { + throw new RuntimeException("dataAdapter is null"); + } + handlerReader.preconditioning(dataAdapter); + EngineResult execute = handlerReader.execute(dataAdapter, data, development); + if (ObjectUtils.isEmpty(execute)) { + throw new RuntimeException("执行结果错误"); + } + return execute.getResult(); + } + + + protected EngineResult mockExecute(Long adapterId, String code, Object data, boolean development) { + //获取当当前接口对应的数据适配器 + DataAdapter dataAdapter = dataAdapterMapper.selectById(adapterId); + if (ObjectUtils.isEmpty(dataAdapter)) { + throw new RuntimeException("dataAdapter is null"); + } + dataAdapter.setCode(code); + handlerReader.preconditioning(dataAdapter); + EngineResult execute = handlerReader.execute(dataAdapter, data, development); + if (ObjectUtils.isEmpty(execute)) { + throw new RuntimeException("执行结果错误"); + } + dataAdapterMapper.updateCode(dataAdapter); + return execute; + } + + + @Override + public boolean remove(Long adapterId) { + if (ObjectUtils.isEmpty(adapterId)) { + throw new RuntimeException("adapterId is null"); + } + DataAdapter dataAdapter = dataAdapterMapper.selectById(adapterId); + if (ObjectUtils.isEmpty(dataAdapter)) { + throw new RuntimeException("dataAdapter is null"); + } + return handlerReader.remove(dataAdapter); + } + +} diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/DataAdapterHandler.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/DataAdapterHandler.java index 32d4638..a2c12b2 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/DataAdapterHandler.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/DataAdapterHandler.java @@ -1,8 +1,10 @@ package cn.fateverse.query.handler.adapter; -import cn.fateverse.query.entity.DataAdapter; +import cn.fateverse.query.entity.dto.MockParam; import cn.fateverse.query.entity.bo.PortalBo; +import javax.servlet.http.HttpServletRequest; + /** * @author Clay * @date 2023-10-31 20:52 @@ -12,19 +14,27 @@ public interface DataAdapterHandler { /** * 模拟执行 * - * @param dataAdapter 数据适配器信息 - * @param portal + * @param portal 接口对象 + * @param mockParam 请求头 * @return 执行结果 */ - Object mockExecute(DataAdapter dataAdapter, PortalBo portal, Object param); + Object mockExecute(PortalBo portal, MockParam mockParam); /** * 真实执行 * - * @param dataAdapter 数据适配器信息 - * @param portal + * @param portal 接口对象 + * @param request * @return 执行结果 */ - Object execute(DataAdapter dataAdapter, PortalBo portal, Object param); + Object execute(PortalBo portal, HttpServletRequest request); + + /** + * 删除数据适配器 + * + * @param adapterId 数据适配器id + * @return 删除结果 + */ + boolean remove(Long adapterId); } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/ExternalDataAdapterHandler.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/ExternalDataAdapterHandler.java new file mode 100644 index 0000000..2682ec4 --- /dev/null +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/ExternalDataAdapterHandler.java @@ -0,0 +1,73 @@ +package cn.fateverse.query.handler.adapter.impl; + +import cn.fateverse.common.core.exception.CustomException; +import cn.fateverse.query.entity.dto.MockParam; +import cn.fateverse.query.entity.bo.PortalBo; +import cn.fateverse.query.enums.PortalEnum; +import cn.fateverse.query.handler.adapter.AbstractDataAdapterHandler; +import cn.fateverse.query.handler.reader.EngineExecuteHandlerReader; +import cn.fateverse.query.mapper.DataAdapterMapper; +import com.alibaba.fastjson2.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; + +/** + * @author Clay + * @date 2024/4/19 22:12 + */ +@Slf4j +@Service +public class ExternalDataAdapterHandler extends AbstractDataAdapterHandler { + + /** + * 请求对象 + */ + private final RestTemplate restTemplate; + + public ExternalDataAdapterHandler(DataAdapterMapper dataAdapterMapper, + EngineExecuteHandlerReader handlerReader, + RestTemplate restTemplate) { + super(dataAdapterMapper, handlerReader); + this.restTemplate = restTemplate; + } + + + @Override + public Object mockExecute(PortalBo portal, MockParam mockParam) { + if (!PortalEnum.EXTERNAL.equals(portal.getType())) { + return null; + } + HttpHeaders headers = new HttpHeaders(); + MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8"); + headers.setContentType(type); + headers.add("Accept", MediaType.APPLICATION_JSON.toString()); + HashMap map = new HashMap<>(); + JSONObject response = null; + switch (portal.getRequestMethod()) { + case "GET": + response = restTemplate.getForObject(portal.getUrl(), JSONObject.class, map); + break; + case "POST": + response = restTemplate.postForObject(portal.getUrl(), map, JSONObject.class); + break; + default: + throw new CustomException("请求方式错误"); + } + if (portal.getCreateDataAdapter()) { + return super.execute(portal.getAdapterId(), response, true); + } else { + return response; + } + } + + @Override + public Object execute(PortalBo portal, HttpServletRequest request) { + return null; + } +} diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/LocalDataAdapterHandler.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/LocalDataAdapterHandler.java index d5cd0c3..556de02 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/LocalDataAdapterHandler.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/adapter/impl/LocalDataAdapterHandler.java @@ -2,20 +2,23 @@ package cn.fateverse.query.handler.adapter.impl; import cn.fateverse.common.core.exception.CustomException; import cn.fateverse.common.core.result.page.TableDataInfo; -import cn.fateverse.query.entity.DataAdapter; +import cn.fateverse.query.entity.dto.MockParam; +import cn.fateverse.query.entity.PortalMapping; import cn.fateverse.query.entity.UniQuery; import cn.fateverse.query.entity.bo.PortalBo; -import cn.fateverse.query.entity.dto.SearchInfo; +import cn.fateverse.query.entity.dto.UniConDto; import cn.fateverse.query.enums.PortalEnum; -import cn.fateverse.query.handler.adapter.DataAdapterHandler; +import cn.fateverse.query.handler.adapter.AbstractDataAdapterHandler; import cn.fateverse.query.handler.reader.EngineExecuteHandlerReader; +import cn.fateverse.query.mapper.DataAdapterMapper; import cn.fateverse.query.mapper.UniQueryMapper; import cn.fateverse.query.service.DynamicDataSearchService; -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.TypeReference; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -25,55 +28,86 @@ import java.util.Map; */ @Slf4j @Service -public class LocalDataAdapterHandler implements DataAdapterHandler { +public class LocalDataAdapterHandler extends AbstractDataAdapterHandler { private final UniQueryMapper uniQueryMapper; - - private final EngineExecuteHandlerReader handlerReader; - private final DynamicDataSearchService dynamicDataSearchService; public LocalDataAdapterHandler(UniQueryMapper uniQueryMapper, + DataAdapterMapper dataAdapterMapper, EngineExecuteHandlerReader handlerReader, DynamicDataSearchService dynamicDataSearchService) { + super(dataAdapterMapper, handlerReader); this.uniQueryMapper = uniQueryMapper; - this.handlerReader = handlerReader; this.dynamicDataSearchService = dynamicDataSearchService; } @Override - public Object mockExecute(DataAdapter dataAdapter, PortalBo portal, Object param) { + public Object mockExecute(PortalBo portal, MockParam mockParam) { if (portal.getType() != PortalEnum.LOCAL) { return null; } - handlerReader.preconditioning(dataAdapter); - if (null == param) { - throw new CustomException("参数对象不能为空"); + //自定义查询编辑查询对象 + List uniConList = new ArrayList<>(); + if (!ObjectUtils.isEmpty(mockParam.getParams())) { + for (MockParam.Param param : mockParam.getParams()) { + if (!ObjectUtils.isEmpty(param.getKey()) && !ObjectUtils.isEmpty(param.getValue())) { + UniConDto uniCon = new UniConDto(); + uniCon.setQuery(param.getValue()); + uniCon.setUcId(Long.parseLong(param.getKey())); + } + } } - if (!(param instanceof SearchInfo)) { - throw new CustomException("数据类型不匹配"); - } - SearchInfo info = (SearchInfo) param; UniQuery query = uniQueryMapper.selectSampleById(portal.getQueryId()); if (null == query) { throw new CustomException("数据源为空!"); } //根据设置的参数动态调整当前是否需要分页操作 - TableDataInfo> tableDataInfo = dynamicDataSearchService.searchData(info.getList(), query, null, Boolean.TRUE); - return handlerReader.execute(dataAdapter, tableDataInfo.getRows(), true); + TableDataInfo> tableDataInfo = dynamicDataSearchService.searchData(uniConList, query, null, Boolean.TRUE); + if (portal.getCreateDataAdapter()) { + return super.mockExecute(portal.getAdapterId(), mockParam.getCode(), tableDataInfo.getRows(), true); + } else { + return tableDataInfo.getRows(); + } } @Override - public Object execute(DataAdapter dataAdapter, PortalBo portal, Object param) { + public Object execute(PortalBo portal, HttpServletRequest request) { if (portal.getType() != PortalEnum.LOCAL) { return null; } - handlerReader.preconditioning(dataAdapter); - List> data = JSON.parseObject(dataAdapter.getMockData(), new TypeReference>>() { - }); - return handlerReader.execute(dataAdapter, data, false); + //自定义查询编辑查询对象 + List uniConList = new ArrayList<>(); + //根据映射关系从request中获取请求参数 + for (PortalMapping portalMapping : portal.getMappings()) { + UniConDto uniCon = new UniConDto(); + String mappingValue = portalMapping.getMappingValue(); + String mappingKey = portalMapping.getMappingKey(); + uniCon.setUcId(Long.parseLong(mappingValue)); + if (portalMapping.getMappingType() == 0) { + uniCon.setQuery(request.getParameter(mappingKey)); + } else if (portalMapping.getMappingType() == 1) { + uniCon.setQuery(request.getHeaders(mappingKey)); + } else { + uniCon.setQuery(request.getParameter(mappingKey)); + } + uniConList.add(uniCon); + } + UniQuery query = uniQueryMapper.selectSampleById(portal.getQueryId()); + if (null == query) { + throw new CustomException("数据源为空!"); + } + //根据设置的参数动态调整当前是否需要分页操作 + TableDataInfo> tableDataInfo = dynamicDataSearchService.searchData(uniConList, query, null, Boolean.TRUE); + if (portal.getCreateDataAdapter()) { + return super.execute(portal.getAdapterId(), tableDataInfo.getRows(), false); + } else { + return tableDataInfo.getRows(); + } } + + } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/EngineExecuteHandler.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/EngineExecuteHandler.java index 708b751..5db4504 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/EngineExecuteHandler.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/EngineExecuteHandler.java @@ -1,5 +1,6 @@ package cn.fateverse.query.handler.engine; +import cn.fateverse.common.code.model.EngineResult; import cn.fateverse.query.entity.DataAdapter; public interface EngineExecuteHandler { @@ -13,7 +14,7 @@ public interface EngineExecuteHandler { * @param development * @return JSONObject对象 */ - Object execute(DataAdapter dataAdapter, Object data, boolean development); + EngineResult execute(DataAdapter dataAdapter, Object data, boolean development); /** * 预处理数据适配器 @@ -25,6 +26,7 @@ public interface EngineExecuteHandler { /** * 删除数据适配器 + * * @param dataAdapter 数据适配器 * @return 删除结果 */ diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaEngineExecuteHandler.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaEngineExecuteHandler.java index 357f509..431f03d 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaEngineExecuteHandler.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaEngineExecuteHandler.java @@ -1,6 +1,7 @@ package cn.fateverse.query.handler.engine.impl; import cn.fateverse.common.code.engine.JavaCodeEngine; +import cn.fateverse.common.code.model.EngineResult; import cn.fateverse.common.core.exception.CustomException; import cn.fateverse.query.entity.DataAdapter; import cn.fateverse.query.enums.DataAdapterType; @@ -31,8 +32,8 @@ public class JavaEngineExecuteHandler implements EngineExecuteHandler { @Override - public Object execute(DataAdapter dataAdapter, Object data, boolean development) { - if (!DataAdapterType.JAVA.equals(dataAdapter.getType())){ + public EngineResult execute(DataAdapter dataAdapter, Object data, boolean development) { + if (!DataAdapterType.JAVA.equals(dataAdapter.getType())) { return null; } return javaCodeEngine.execute(dataAdapter.getExecuteCode(), getClassName(dataAdapter), diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaScriptEngineExecuteHandler.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaScriptEngineExecuteHandler.java index 945ea28..9f08e1a 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaScriptEngineExecuteHandler.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/engine/impl/JavaScriptEngineExecuteHandler.java @@ -1,12 +1,17 @@ package cn.fateverse.query.handler.engine.impl; import cn.fateverse.common.code.engine.JavaScriptEngine; +import cn.fateverse.common.code.model.EngineResult; +import cn.fateverse.common.core.exception.CustomException; import cn.fateverse.query.entity.DataAdapter; import cn.fateverse.query.enums.DataAdapterType; import cn.fateverse.query.handler.engine.EngineExecuteHandler; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * JavaScript 代码执行器 * @@ -18,19 +23,31 @@ import org.springframework.stereotype.Component; public class JavaScriptEngineExecuteHandler implements EngineExecuteHandler { @Override - public Object execute(DataAdapter dataAdapter, Object data, boolean development) { + public EngineResult execute(DataAdapter dataAdapter, Object data, boolean development) { if (!DataAdapterType.JAVA_SCRIPT.equals(dataAdapter.getType())) { return null; } - return JavaScriptEngine.executeScript(dataAdapter.getExecuteCode(), "execute", data); + return JavaScriptEngine.execute(dataAdapter.getExecuteCode(), "execute" + dataAdapter.getAdapterId(), development, data); } @Override public Boolean preconditioning(DataAdapter dataAdapter) { - if (DataAdapterType.JAVA_SCRIPT.equals(dataAdapter.getType())) { - return Boolean.TRUE; + if (!DataAdapterType.JAVA_SCRIPT.equals(dataAdapter.getType())) { + return Boolean.FALSE; } - return Boolean.FALSE; + String code = dataAdapter.getCode(); + // 正则表达式匹配类定义 + String regex = "function .*? "; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(code); + if (matcher.find()) { + // 执行替换操作 + String replacedCode = code.replaceFirst(regex, "function execute" + dataAdapter.getAdapterId() + "(data) "); + dataAdapter.setExecuteCode(replacedCode); + } else { + throw new CustomException("请勿修改类定义"); + } + return Boolean.TRUE; } @Override diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/DataAdapterHandlerReader.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/DataAdapterHandlerReader.java index 4975f8c..6ff1a29 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/DataAdapterHandlerReader.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/DataAdapterHandlerReader.java @@ -2,12 +2,13 @@ package cn.fateverse.query.handler.reader; import cn.fateverse.common.core.exception.CustomException; -import cn.fateverse.query.entity.DataAdapter; +import cn.fateverse.query.entity.dto.MockParam; import cn.fateverse.query.entity.bo.PortalBo; import cn.fateverse.query.handler.adapter.DataAdapterHandler; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import javax.servlet.http.HttpServletRequest; import java.util.List; /** @@ -28,9 +29,9 @@ public class DataAdapterHandlerReader { } - public Object mockExecute(DataAdapter dataAdapter, PortalBo portal, Object params) { + public Object mockExecute(PortalBo portal, MockParam mockParam) { for (DataAdapterHandler dataAdapterHandler : handlerList) { - Object result = dataAdapterHandler.mockExecute(dataAdapter, portal, params); + Object result = dataAdapterHandler.mockExecute(portal, mockParam); if (result != null) { return result; } @@ -39,9 +40,9 @@ public class DataAdapterHandlerReader { } - public Object execute(DataAdapter dataAdapter, PortalBo portal, Object params) { + public Object execute(PortalBo portal, HttpServletRequest request) { for (DataAdapterHandler dataAdapterHandler : handlerList) { - Object result = dataAdapterHandler.execute(dataAdapter, portal, params); + Object result = dataAdapterHandler.execute(portal, request); if (result != null) { return result; } @@ -49,5 +50,15 @@ public class DataAdapterHandlerReader { throw new CustomException("当前数据源类型不支持!"); } + public Boolean remove(Long adaptorId) { + for (DataAdapterHandler dataAdapterHandler : handlerList) { + boolean result = dataAdapterHandler.remove(adaptorId); + if (result) { + return true; + } + } + return false; + } + } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/EngineExecuteHandlerReader.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/EngineExecuteHandlerReader.java index 7e84e5e..60a3e93 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/EngineExecuteHandlerReader.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/handler/reader/EngineExecuteHandlerReader.java @@ -1,5 +1,6 @@ package cn.fateverse.query.handler.reader; +import cn.fateverse.common.code.model.EngineResult; import cn.fateverse.query.entity.DataAdapter; import cn.fateverse.query.handler.engine.EngineExecuteHandler; import lombok.extern.slf4j.Slf4j; @@ -47,11 +48,11 @@ public class EngineExecuteHandlerReader { * @param data 数据列表 * @return 执行结果 */ - public Object execute(DataAdapter dataAdapter, Object data, boolean development) { + public EngineResult execute(DataAdapter dataAdapter, Object data, boolean development) { // 遍历引擎执行处理器列表 for (EngineExecuteHandler engineExecuteHandler : handlerList) { // 执行数据适配器的处理方法 - Object result = engineExecuteHandler.execute(dataAdapter, data, development); + EngineResult result = engineExecuteHandler.execute(dataAdapter, data, development); if (result != null) { return result; } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/DataAdapterMapper.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/DataAdapterMapper.java index 02e293d..f469b42 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/DataAdapterMapper.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/DataAdapterMapper.java @@ -48,6 +48,14 @@ public interface DataAdapterMapper { */ int update(DataAdapter dataAdapter); + /** + * 更新代码 + * + * @param dataAdapter 数据适配器 + * @return 结果 + */ + int updateCode(DataAdapter dataAdapter); + /** * 删除数据源适配器 * diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/PortalMapper.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/PortalMapper.java index 6e8961c..41c97e9 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/PortalMapper.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/mapper/PortalMapper.java @@ -48,4 +48,28 @@ public interface PortalMapper { * @return 更新数量 */ int insert(Portal portal); + + /** + * 修改接口 + * + * @param portal 接口信息 + * @return 更新数量 + */ + int update(Portal portal); + + /** + * 更新状态 + * + * @param portalId 接口id + * @param state 状态 + */ + void updateState(@Param("portalId") Long portalId, @Param("state") Integer state); + + /** + * 删除 + * + * @param portalId id + * @return 删除行数 + */ + int deleteById(Long portalId); } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java index fe80175..cf443cf 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/PortalDispatchServlet.java @@ -70,34 +70,13 @@ public class PortalDispatchServlet { portalBo = PortalBo.toPortalBo(portal, portalMappings); redisTemplate.opsForValue().set(QueryConstant.PORTAL_KEY + portalBo.getPath() + ":" + portalBo.getRequestMethod(), portalBo); } - //自定义查询编辑查询对象 - SearchInfo searchInfo = new SearchInfo(); - List uniConList = new ArrayList<>(); - //根据映射关系从request中获取请求参数 - for (PortalMapping portalMapping : portalBo.getMappings()) { - UniConDto uniCon = new UniConDto(); - String mappingValue = portalMapping.getMappingValue(); - String mappingKey = portalMapping.getMappingKey(); - uniCon.setUcId(Long.parseLong(mappingValue)); - if (portalMapping.getMappingType() == 0) { - uniCon.setQuery(request.getParameter(mappingKey)); - } else if (portalMapping.getMappingType() == 1) { - uniCon.setQuery(request.getHeaders(mappingKey)); - } else { - uniCon.setQuery(request.getParameter(mappingKey)); - } - uniConList.add(uniCon); - } - searchInfo.setList(uniConList); - //获取当当前接口对应的数据适配器 - DataAdapter dataAdapter = dataAdapterMapper.selectById(portalBo.getAdapterId()); //进行数据适配器的执行逻辑 Object result = null; - if (portalBo.getState() == 1 || portalBo.getState() == 2) { - result = dataAdapterHandler.execute(dataAdapter, portalBo, searchInfo); - } else { - result = dataAdapterHandler.mockExecute(dataAdapter, portalBo, searchInfo); - } +// if (portalBo.getState() == 1 || portalBo.getState() == 2) { + result = dataAdapterHandler.execute(portalBo, request); +// } else { +// result = dataAdapterHandler.mockExecute(portalBo, request); +// } //将返回结果放入response ResponseRender.renderString(response, Result.ok(result)); } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java index 89d2705..9e11fb2 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/portal/service/DispatchSyncService.java @@ -140,6 +140,7 @@ public class DispatchSyncService { } } } catch (NacosException e) { + log.error("NacosException: {}", e.getMessage()); throw new RuntimeException(e); } } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/DynamicDataSearchService.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/DynamicDataSearchService.java index d9221bc..9117eac 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/DynamicDataSearchService.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/DynamicDataSearchService.java @@ -71,7 +71,9 @@ public class DynamicDataSearchService { } else { uniConList = uniConMapper.selectByQueryIdAndUcIdList(query.getId(), ids); } - uniConList = uniConList.stream().filter(uniCon -> null != queryMap.get(uniCon.getUcId())).peek(uniCon -> uniCon.setUcMock(queryMap.get(uniCon.getUcId()))).collect(Collectors.toList()); + uniConList = uniConList.stream().filter(uniCon -> null != queryMap.get(uniCon.getUcId())) + .peek(uniCon -> uniCon.setUcMock(queryMap.get(uniCon.getUcId()))) + .collect(Collectors.toList()); if (query.getType() == 1) { SqlSelect select = new SqlSelect(); select.setSelectSql(query.getUqSql()); diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java index 77fa46f..c5a870d 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/PortalService.java @@ -1,6 +1,7 @@ package cn.fateverse.query.service; import cn.fateverse.common.core.result.page.TableDataInfo; +import cn.fateverse.query.entity.dto.MockParam; import cn.fateverse.query.entity.dto.PortalDto; import cn.fateverse.query.entity.query.PortalQuery; import cn.fateverse.query.entity.vo.PortalIdWrapper; @@ -21,6 +22,14 @@ public interface PortalService { */ PortalVo searchById(Long portalId); + /** + * 根据id查询详情 + * + * @param portalId id + * @return 结果 + */ + PortalVo searchDetailById(Long portalId); + /** * 查询接口列表 * @@ -29,6 +38,23 @@ public interface PortalService { */ TableDataInfo searchList(PortalQuery query); + /** + * 模拟执行 + * + * @param mockParam 执行数据 + * @return 执行结果 + */ + Object mockExecute(MockParam mockParam); + + + /** + * 获取到模拟数据 + * + * @param mockParam + * @return + */ + Object mockData(MockParam mockParam); + /** * 保存接口信息 * @@ -44,4 +70,19 @@ public interface PortalService { * @return 修改完成后接口id和数据适配器id */ PortalIdWrapper edit(PortalDto portalDto); + + /** + * 取消发布 + * + * @param portalId 接口id + */ + void cancel(Long portalId); + + /** + * 删除接口信息 + * + * @param portalId 接口id + */ + void delete(Long portalId); + } diff --git a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java index b41e856..0b3ad93 100644 --- a/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java +++ b/custom-query/custom-query-biz/src/main/java/cn/fateverse/query/service/impl/PortalServiceImpl.java @@ -3,14 +3,14 @@ package cn.fateverse.query.service.impl; import cn.fateverse.common.core.exception.CustomException; import cn.fateverse.common.core.result.page.TableDataInfo; import cn.fateverse.common.mybatis.utils.PageUtils; +import cn.fateverse.query.entity.*; import cn.fateverse.query.entity.bo.PortalBo; +import cn.fateverse.query.entity.dto.MockParam; +import cn.fateverse.query.entity.vo.DataAdapterVo; import cn.fateverse.query.entity.vo.PortalIdWrapper; +import cn.fateverse.query.handler.reader.DataAdapterHandlerReader; import cn.fateverse.query.portal.service.HandlerMethodService; import cn.fateverse.query.constant.QueryConstant; -import cn.fateverse.query.entity.DataAdapter; -import cn.fateverse.query.entity.Portal; -import cn.fateverse.query.entity.PortalMapping; -import cn.fateverse.query.entity.UniQuery; import cn.fateverse.query.entity.dto.DataAdapterDto; import cn.fateverse.query.entity.dto.PortalDto; import cn.fateverse.query.entity.query.PortalQuery; @@ -32,7 +32,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import javax.annotation.Resource; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -57,19 +56,26 @@ public class PortalServiceImpl implements PortalService { private final PortalMappingMapper portalMappingMapper; + + private final DataAdapterHandlerReader handlerReader; + public PortalServiceImpl(PortalMapper portalMapper, UniQueryMapper queryMapper, DataAdapterMapper adapterMapper, PortalMappingMapper portalMappingMapper, ThreadPoolTaskExecutor taskExecuteExecutor, - HandlerMethodService methodService) { + HandlerMethodService methodService, + DataAdapterHandlerReader handlerReader) { this.portalMapper = portalMapper; this.queryMapper = queryMapper; this.adapterMapper = adapterMapper; this.portalMappingMapper = portalMappingMapper; this.methodService = methodService; + this.handlerReader = handlerReader; taskExecuteExecutor.execute(() -> { - List portalList = portalMapper.selectList(new PortalQuery()); + PortalQuery query = new PortalQuery(); +// query.setState(QueryConstant.PORTAL_PUBLISH); + List portalList = portalMapper.selectList(query); if (ObjectUtils.isEmpty(portalList)) { log.info("portal is empty!"); return; @@ -116,6 +122,20 @@ public class PortalServiceImpl implements PortalService { return portalVo; } + @Override + public PortalVo searchDetailById(Long portalId) { + PortalVo portalVo = searchById(portalId); + if (!ObjectUtils.isEmpty(portalVo.getAdapterId()) && portalVo.getCreateDataAdapter()) { + DataAdapter dataAdapter = adapterMapper.selectById(portalVo.getAdapterId()); + if (ObjectUtils.isEmpty(dataAdapter)) { + return portalVo; + } + DataAdapterVo dataAdapterVo = DataAdapterVo.toDataAdapterVo(dataAdapter); + portalVo.setDataAdapter(dataAdapterVo); + } + return portalVo; + } + @Override public TableDataInfo searchList(PortalQuery query) { PageUtils.startPage(); @@ -162,6 +182,21 @@ public class PortalServiceImpl implements PortalService { }); } + @Override + public Object mockExecute(MockParam mockParam) { + Portal portal = portalMapper.selectById(mockParam.getPortalId()); + PortalBo portalBo = PortalBo.toPortalBo(portal, null); + return handlerReader.mockExecute(portalBo, mockParam); + } + + + @Override + public Object mockData(MockParam mockParam) { + Portal portal = portalMapper.selectById(mockParam.getPortalId()); + PortalBo portalBo = PortalBo.toPortalBo(portal, null); + portalBo.setCreateDataAdapter(false); + return handlerReader.mockExecute(portalBo, mockParam); + } @Override @Transactional(rollbackFor = Exception.class) @@ -176,7 +211,7 @@ public class PortalServiceImpl implements PortalService { if (ObjectUtils.isEmpty(uniQuery)) { throw new CustomException("未找到对应的查询接口!"); } - portal.setState(0); + portal.setState(QueryConstant.PORTAL_DEV); // 判断是否需要创建数据适配器 if (portal.getCreateDataAdapter()) { createDataAdapter(portalDto, portal); @@ -203,6 +238,7 @@ public class PortalServiceImpl implements PortalService { } @Override + @Transactional(rollbackFor = Exception.class) public PortalIdWrapper edit(PortalDto portalDto) { Portal portal = portalDto.toPortal(); checkPortalType(portal); @@ -210,7 +246,6 @@ public class PortalServiceImpl implements PortalService { if (!ObjectUtils.isEmpty(old) && !old.getPortalId().equals(portal.getPortalId())) { throw new CustomException("系统中存在当前请求路径"); } - if (portal.getCreateDataAdapter() != old.getCreateDataAdapter()) { if (portal.getCreateDataAdapter()) { createDataAdapter(portalDto, portal); @@ -218,51 +253,55 @@ public class PortalServiceImpl implements PortalService { adapterMapper.deleteById(old.getAdapterId()); } } - PortalBo portalBo = PortalBo.toPortalBo(portal, portalDto.getMappings()); - //存在接口路径或者请求类型不同则需要重新发布 - if (!old.getPath().equals(portal.getPath()) - || !old.getRequestMethod().equals(portal.getRequestMethod())) { - //先卸载接口,需要进行数据同步 - unpublishPortal(old, true); - //注册新的映射 - methodService.registerMapping(portalBo.getPath(), RequestMethod.valueOf(portalBo.getRequestMethod()), true); + portalMappingMapper.deleteByPortalId(portal.getPortalId()); + portalMapper.update(portal); + if (!ObjectUtils.isEmpty(portalDto.getMappings())) { + List mappings = portalDto.getMappings(); + for (PortalMapping mapping : mappings) { + mapping.setPortalId(portal.getPortalId()); + } + portalMappingMapper.insertBatch(mappings); } - //修改Redis中的数据信息 - redisTemplate.opsForValue().set(QueryConstant.PORTAL_KEY + portalBo.getPath() + ":" + portalBo.getRequestMethod(), portalBo); //返回接口id和适配器id return PortalIdWrapper.builder() .portalId(String.valueOf(portal.getPortalId())) .adapterId(String.valueOf(portal.getAdapterId())) .build(); - } - private boolean mappingCheckEquals(List oldPortalMappingList, List mappings) { - if (ObjectUtils.isEmpty(oldPortalMappingList) && ObjectUtils.isEmpty(mappings)) { - return true; + @Override + public void cancel(Long portalId) { + Portal portal = portalMapper.selectById(portalId); + if (ObjectUtils.isEmpty(portal)) { + return; } - if (ObjectUtils.isEmpty(oldPortalMappingList) || ObjectUtils.isEmpty(mappings)) { - return false; + if (QueryConstant.PORTAL_DEV.equals(portal.getState())) { + throw new CustomException("当前状态错误"); } - Optional optional = mappings.stream().filter(ObjectUtils::isEmpty).findAny(); - if (optional.isEmpty()) { - return false; + portalMapper.updateState(portalId, QueryConstant.PORTAL_DEV); + if (QueryConstant.PORTAL_PUBLISH.equals(portal.getState())) { + unpublishPortal(portal, Boolean.TRUE); } - if (oldPortalMappingList.size() == mappings.size()) { - Map oldPortalMappingMap = oldPortalMappingList.stream() - .collect(Collectors.toMap(PortalMapping::getMappingId, Function.identity())); - Map portalMappingMap = mappings.stream() - .collect(Collectors.toMap(PortalMapping::getMappingId, Function.identity())); - for (Long mappingId : oldPortalMappingMap.keySet()) { - PortalMapping portalMapping = portalMappingMap.get(mappingId); - if (ObjectUtils.isEmpty(portalMapping)) { - return false; - } - } - } - return false; } + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long portalId) { + Portal portal = portalMapper.selectById(portalId); + if (ObjectUtils.isEmpty(portal)) { + return; + } + if (!QueryConstant.PORTAL_DEV.equals(portal.getState())) { + throw new CustomException("当前状态不允许删除"); + } + if (portal.getCreateDataAdapter()) { + adapterMapper.deleteById(portal.getAdapterId()); + } + portalMappingMapper.deleteByPortalId(portalId); + portalMapper.deleteById(portalId); + } + + /** * 发布接口 * @@ -302,7 +341,7 @@ public class PortalServiceImpl implements PortalService { if (ObjectUtils.isEmpty(dataAdapter.getType())) { throw new CustomException("请选择数据适配器类型!"); } - dataAdapter.setAdapterName(portal.getPortalName() + "专用数据适配器!"); + dataAdapter.setAdapterName(portal.getPortalName() + "专用"); dataAdapter.setCommon(Boolean.FALSE); //初始化对应的数据适配器 dataAdapter.init(); diff --git a/custom-query/custom-query-biz/src/main/resources/mapper/DataAdapterMapper.xml b/custom-query/custom-query-biz/src/main/resources/mapper/DataAdapterMapper.xml index 0b9ac8b..cff9939 100644 --- a/custom-query/custom-query-biz/src/main/resources/mapper/DataAdapterMapper.xml +++ b/custom-query/custom-query-biz/src/main/resources/mapper/DataAdapterMapper.xml @@ -20,9 +20,10 @@ select adapter_id, adapter_name, - `type`, + type, common, code, + execute_code, mock_data, create_by, create_time, @@ -35,8 +36,10 @@ @@ -58,7 +61,7 @@ insert into data_adapter adapter_name, - `type`, + type, common, code, mock_data, @@ -80,7 +83,7 @@ update data_adapter adapter_name = #{adapterName}, - `type` = #{type}, + type = #{type}, code = #{code}, mock_data = #{mockData}, update_by = #{updateBy}, @@ -89,6 +92,18 @@ where adapter_id = #{adapterId} + + update data_adapter + + code = #{code}, + execute_code = #{code}, + mock_data = #{mockData}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + where adapter_id = #{adapterId} + + delete from data_adapter diff --git a/custom-query/custom-query-biz/src/main/resources/mapper/PortalMapper.xml b/custom-query/custom-query-biz/src/main/resources/mapper/PortalMapper.xml index a88c432..3fe99ba 100644 --- a/custom-query/custom-query-biz/src/main/resources/mapper/PortalMapper.xml +++ b/custom-query/custom-query-biz/src/main/resources/mapper/PortalMapper.xml @@ -13,6 +13,7 @@ type, request_method, create_data_adapter, + page, path, url, state, @@ -23,7 +24,6 @@ remark from portal - - and portal_name like concat('%', #{portalName}, '%') + and portal_name like concat('%', #{portalName}, '%') and anonymity = #{anonymity} and type = #{type} + and state = #{state} and path like concat('%', #{path}, '%') @@ -52,6 +53,7 @@ portal_name, anonymity, type, + page, request_method, create_data_adapter, path, @@ -66,6 +68,7 @@ #{portalName}, #{anonymity}, #{type}, + #{page}, #{requestMethod}, #{createDataAdapter}, #{path}, @@ -75,4 +78,35 @@ #{createTime}, + + + update portal + + query_id = #{queryId}, + adapter_id = #{adapterId}, + portal_name = #{portalName}, + anonymity = #{anonymity}, + type = #{type}, + type = #{page}, + request_method = #{requestMethod}, + create_data_adapter = #{createDataAdapter}, + path = #{path}, + url = #{url}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + where portal_id = #{portalId} + + + + update portal + set state = #{state} + where portal_id = #{portalId} + + + + delete + from portal + where portal_id = #{portalId} + \ No newline at end of file diff --git a/custom-query/custom-query-biz/src/main/resources/mapper/PortalMappingMapper.xml b/custom-query/custom-query-biz/src/main/resources/mapper/PortalMappingMapper.xml index 9f6d8ab..2b8f4be 100644 --- a/custom-query/custom-query-biz/src/main/resources/mapper/PortalMappingMapper.xml +++ b/custom-query/custom-query-biz/src/main/resources/mapper/PortalMappingMapper.xml @@ -4,7 +4,7 @@ "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - select mapping_id, portal_id, mapping_key, mapping_type, mapping_value + select mapping_id, portal_id, mapping_key, mapping_type, mapping_value, input_type, description from portal_mapping @@ -23,10 +23,11 @@ - insert into portal_mapping (portal_id, mapping_key, mapping_type, mapping_value) + insert into portal_mapping (portal_id, mapping_key, mapping_type, mapping_value, input_type, description) values - (#{item.portalId}, #{item.mappingKey}, #{item.mappingType}, #{item.mappingValue}) + (#{item.portalId}, #{item.mappingKey}, #{item.mappingType}, #{item.mappingValue}, #{item.inputType}, + #{item.description}) diff --git a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/ConsoleCapture.java b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/ConsoleCapture.java new file mode 100644 index 0000000..fae08b2 --- /dev/null +++ b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/ConsoleCapture.java @@ -0,0 +1,32 @@ +package cn.fateverse.query; + +import java.io.*; + + public class ConsoleCapture { + public static String captureOutput(Runnable codeToRun) throws IOException { + PrintStream originalOut = System.out; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream capturingOut = new PrintStream(baos); + + try { + System.setOut(capturingOut); + codeToRun.run(); + } finally { + System.setOut(originalOut); + } + + return baos.toString(); + } + + // 使用示例 + public static void main(String[] args) throws IOException { + String capturedText = captureOutput(() -> { + System.out.println("Hello, Console!"); + System.out.println("This is being captured."); + }); + + System.out.println("Captured output:"); + System.out.println(capturedText); + } + } + \ No newline at end of file diff --git a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter.java b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter.java deleted file mode 100644 index 2d5ab74..0000000 --- a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.fateverse.query; - -import java.util.*; -import java.util.stream.*; - -public class DataAdapter { - - public static Object execute(List> data) { - for (Map objectMap : data) { - objectMap.remove("oper_location"); - } - return data; - } -} \ No newline at end of file diff --git a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter1100.java b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter1100.java new file mode 100644 index 0000000..1f8b529 --- /dev/null +++ b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/DataAdapter1100.java @@ -0,0 +1,16 @@ +package cn.fateverse.query; + +/** + * @author Clay + * @date 2024/4/22 18:59 + */ +public class DataAdapter1100 { + + public static Object execute(String data) { + for (int i = 0; i < 1000; i++) { + System.out.println(i); + } + return "qwewe"; + } + +} diff --git a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptParamTest.java b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptParamTest.java new file mode 100644 index 0000000..ff04661 --- /dev/null +++ b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptParamTest.java @@ -0,0 +1,77 @@ +package cn.fateverse.query; + +import cn.fateverse.common.code.engine.JavaScriptEngine; +import cn.fateverse.common.code.model.EngineResult; +import com.alibaba.fastjson2.JSONObject; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; +import org.junit.jupiter.api.Test; + +import javax.script.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +/** + * @author Clay + * @date 2024/4/23 9:42 + */ +public class JavaScriptParamTest { + + + static String finalCode = "function execute1(data) {\n" + + " let res = [data.length];\n" + + " for (let i = 0; i < data.length; i++) {\n" + + " console.log(data[i])\n" + + " console.log(data[i].foo)\n" + + " res[i] = data[i].foo\n" + + " }\n" + + " return res;\n" + + "}"; + + @Test + public void testParam() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + + Map param = new HashMap<>(); + param.put("foo", "sdsdsdsds"); + list.add(param); + } + + ScriptEngineManager engineManager = new ScriptEngineManager(); + ScriptEngine jsEngine = engineManager.getEngineByName("graal.js"); + Context context = Context.newBuilder() + .allowAllAccess(true) + .build(); +// Context context = Context.create(); + context.eval("js", finalCode); + + Value executeFunction = context.getBindings("js").getMember("execute1"); + Value javaObjectAsValue = Value.asValue(list); + Value result = executeFunction.execute(javaObjectAsValue); + System.out.println(result); + + } + + + @Test + public void testParam2() throws Exception { + + ScriptEngineManager engineManager = new ScriptEngineManager(); + ScriptEngine jsEngine = engineManager.getEngineByName("graal.js"); + Invocable funcCall = (Invocable) jsEngine; + Bindings bindings = jsEngine.getBindings(ScriptContext.ENGINE_SCOPE); + bindings.put("polyglot.js.allowHostAccess", true); + bindings.put("polyglot.js.allowHostClassLookup", (Predicate) s -> true); + + jsEngine.eval(finalCode); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("foo", "sdsdsdsds"); + Object res= funcCall.invokeFunction("execute1", jsonObject); + + } + +} diff --git a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptTest.java b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptTest.java new file mode 100644 index 0000000..50ae687 --- /dev/null +++ b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/JavaScriptTest.java @@ -0,0 +1,122 @@ +package cn.fateverse.query; + +import cn.fateverse.common.code.config.JavaCodeProperties; +import cn.fateverse.common.code.engine.JavaCodeEngine; +import cn.fateverse.common.code.engine.JavaScriptEngine; +import cn.fateverse.common.code.model.EngineResult; + +import java.util.concurrent.FutureTask; + + +/** + * @author Clay + * @date 2024/4/22 16:04 + */ +public class JavaScriptTest { + public static void main(String[] args) throws Exception { + String code = "function execute(data) {\n" + + " console.log(data)\n" + + " console.log(\"test console!\")\n" + + " let add = (a, b) => a + b; // 使用箭头函数\n" + + " console.log(\"Adding 5 and 3:\", add(5, 3));\n\n" + + " for (let i = 0; i < 1000; i++) {\n" + + " console.log(i)\n" + + " }" + + " return \"success\";\n" + + "}"; + + + JavaCodeProperties properties = new JavaCodeProperties(); + properties.setClassPath("C:\\home\\clay\\code\\"); + JavaCodeEngine javaCodeEngine = new JavaCodeEngine(properties); + + +// EngineResult executeScript = JavaScriptEngine.executeScript(code, "execute", "测试控制台输出"); + + String finalCode = "function execute(data) {\n" + + " console.log(data)\n" + + " console.log(\"test console!\")\n" + + " let add = (a, b) => a + b; // 使用箭头函数\n" + + " console.log(\"Adding 5 and 3:\", add(5, 3));\n\n" + + " for (let i = 0; i < 1000; i++) {\n" + + " console.log(i)\n" + + " }" + + " return \"success\";\n" + + "}"; + FutureTask engineResultFutureTask = new FutureTask<>(() -> { + return JavaScriptEngine.execute(finalCode, "execute", false, "测试控制台输出"); + }); + + + String finalCode1 = "import java.util.*;\n" + + "import java.util.stream.*;\n" + + "\n" + + "public class DataAdapter100 {" + + "\n" + + " public static Object execute(String data) {\n" + + " for (int i = 0; i < 1000; i++) {\n" + + " System.out.println(i);\n" + + " }\n" + + " return \"qwewe\";\n" + + " }" + + "}\n"; + FutureTask engineResultFutureTask1 = new FutureTask<>(() -> { + return javaCodeEngine.execute(finalCode1, "DataAdapter100", "execute", new Class[]{String.class}, new Object[]{"test"}, true); + }); + new Thread(engineResultFutureTask).start(); + new Thread(engineResultFutureTask1).start(); +// EngineResult execute = javaCodeEngine.execute(code, "DataAdapter100", "execute", new Class[]{String.class}, new Object[]{"test"}, true); + + + EngineResult x = engineResultFutureTask.get(); + EngineResult x1 = engineResultFutureTask1.get(); + System.out.println(x); + System.out.println(x1); + + +// EngineResult capture = MultiThreadedCapture.capture(() -> { +// ScriptEngine engine = new ScriptEngineManager().getEngineByName("graal.js"); +// Invocable inv = (Invocable) engine; +// try { +// engine.eval(finalCode); +// return inv.invokeFunction("execute", "args"); +// } catch (ScriptException | NoSuchMethodException e) { +// throw new RuntimeException(e); +// } +// }); +// System.out.println(capture); +// EngineResult objectEngineResult = JavaScriptEngine.executeScript(finalCode, "execute", "测试控制台输出"); +// +// ByteArrayOutputStream baos = new ByteArrayOutputStream(); +// PrintStream oldOut = System.out; +// System.setOut(new PrintStream(baos)); + + +// EngineResult capture = MultiThreadedCapture.capture(() -> { +// int someNumber = 42; +// System.out.println(someNumber); +// return null; +// }); + + + // 执行产生数值输出的代码 +// System.out.println(objectEngineResult); +// ScriptEngine engine = JavaScriptEngine.getEngine(); +// Invocable inv = (Invocable) engine; +// engine.eval(finalCode); +// inv.invokeFunction("execute", "args"); +// System.out.println(capture); + +// MultiThreadedCapture.executor.shutdown(); + // 恢复标准输出流 +// System.setOut(oldOut); +// +// System.setOut(oldOut); +// // 从捕获的字节数组输出流中获取打印的文本 +// String capturedOutput = baos.toString(); +// System.out.println("Captured output: " + capturedOutput); + + } + + +} diff --git a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/Main.java b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/Main.java new file mode 100644 index 0000000..9749c38 --- /dev/null +++ b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/Main.java @@ -0,0 +1,38 @@ +package cn.fateverse.query; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + public static void main(String[] args) { + // 创建 GraalVM 上下文 + Context context = Context.create(); + + // 定义一个 JavaScript 函数 + String script = "function execute(data) {\n" + + " console.log(data)\n" + + " console.log(\"test console!\")\n" + + " let add = (a, b) => a + b; // 使用箭头函数\n" + + " console.log(\"Adding 5 and 3:\", add(5, 3));\n\n" + + " for (let i = 0; i < 1000; i++) {\n" + + " console.log(i)\n" + + " }" + + " return \"success\";\n" + + "}"; + + // 编译 JavaScript 函数 + context.eval("js", script); + + // 获取函数对象 + Value addFunction = context.getBindings("js").getMember("execute"); + + // 执行函数并传入参数 + Value result = addFunction.execute("测试"); + Value result2 = addFunction.execute("测试"); + // 获取返回值 +// int sum = result.asInt(); + + // 输出结果 + System.out.println("Sum: "); // 输出:Sum: 5 + } +} diff --git a/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/SystemOut.java b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/SystemOut.java new file mode 100644 index 0000000..5b6e8e2 --- /dev/null +++ b/custom-query/custom-query-biz/src/test/java/cn/fateverse/query/SystemOut.java @@ -0,0 +1,45 @@ +package cn.fateverse.query; + +import cn.fateverse.common.code.engine.JavaScriptEngine; +import cn.fateverse.common.code.model.EngineResult; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +public class SystemOut { + public static void outTest() { + ByteArrayOutputStream baoStream = new ByteArrayOutputStream(1024); + PrintStream cacheStream = new PrintStream(baoStream);//临时输出 + PrintStream oldStream = System.out;//缓存系统输出 + System.setOut(cacheStream); + System.out.print("...");//不会打印到控制台 + String result = baoStream.toString();//存放控制台输出的字符串 + System.setOut(oldStream);//还原到系统输出 + System.out.println("result"); + } + + public static void main(String[] args) { +// outTest(); + + String finalCode = "function execute1(data) {\n" + + " console.log(data)\n" + + " console.log(\"test console!\")\n" + + " let add = (a, b) => a + b; // 使用箭头函数\n" + + " console.log(\"Adding 5 and 3:\", add(5, 3));\n\n" + + " for (let i = 0; i < 1000; i++) {\n" + + " console.log(i)\n" + + " }" + + " return \"success\";\n" + + "}"; +// String finalCode = "function myFunction() { return 'Hello, world!'; }"; + long start1 = System.currentTimeMillis(); + EngineResult execute = JavaScriptEngine.execute(finalCode, "execute1", false, "测试控制台输出"); + long start2 = System.currentTimeMillis(); + EngineResult execute1 = JavaScriptEngine.execute(finalCode, "execute1", false, "测试控制台输出"); + long start3 = System.currentTimeMillis(); + System.out.println("耗时1:" + (start2 - start1) + "ms"); + System.out.println("耗时2:" + (start3 - start2) + "ms"); + System.out.println(execute); + + } +} \ No newline at end of file diff --git a/visual/pom.xml b/visual/pom.xml index e4b1e6b..fdb2ec2 100644 --- a/visual/pom.xml +++ b/visual/pom.xml @@ -16,10 +16,10 @@ true - monitor + - sentinel-dashboard + diff --git a/workflow/src/main/java/cn/fateverse/workflow/process/TriggerService.java b/workflow/src/main/java/cn/fateverse/workflow/process/TriggerService.java index 5db6c3c..a4ecdbb 100644 --- a/workflow/src/main/java/cn/fateverse/workflow/process/TriggerService.java +++ b/workflow/src/main/java/cn/fateverse/workflow/process/TriggerService.java @@ -1,6 +1,7 @@ package cn.fateverse.workflow.process; import cn.fateverse.common.code.engine.JavaScriptEngine; +import cn.fateverse.common.code.model.EngineResult; import cn.fateverse.workflow.constant.ProcessConstant; import cn.fateverse.workflow.entity.bpmn.*; import cn.hutool.core.util.StrUtil; @@ -158,14 +159,14 @@ public class TriggerService { } //获取到请求的返回结果 Map result = response.getBody(); - ScriptObjectMirror jsResult; + EngineResult engineResult; try { //判断请求是否有效 if (response.getStatusCode() == HttpStatus.OK) { - jsResult = JavaScriptEngine.executeScript(http.getSuccess(), "handlerSuccess", result); + engineResult = JavaScriptEngine.execute(http.getSuccess(), "handlerSuccess", false, result); operation.setState(OperationStateEnums.SUCCESS); } else { - jsResult = JavaScriptEngine.executeScript(http.getFail(), "handlerFail", result); + engineResult = JavaScriptEngine.execute(http.getFail(), "handlerFail", false, result); operation.setState(OperationStateEnums.FAILURE); } } catch (Exception e) { @@ -177,6 +178,7 @@ public class TriggerService { } return; } + ScriptObjectMirror jsResult = (ScriptObjectMirror) engineResult.getResult(); //获取到自定义脚本的状态 boolean state = (Boolean) jsResult.get("state"); //获取到js脚本中的内容