From eeb1dc4a077b451652dddde2cb1628082917daef Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 25 Mar 2025 20:42:21 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/IotProductScriptLanguageEnum.java | 1 + .../product/IotProductScriptStatusEnum.java | 1 + .../product/IotProductScriptDO.java | 1 + .../product/IotProductScriptServiceImpl.java | 1 + .../plugin/http/IotHttpPluginApplication.java | 10 ++++---- .../plugin/http/script/HttpScriptService.java | 24 ++++++++++++------- .../upstream/IotDeviceUpstreamServer.java | 3 +-- .../router/IotDeviceUpstreamVertxHandler.java | 10 ++++---- .../iot/plugin/script/ScriptExample.java | 1 + .../script/config/ScriptConfiguration.java | 5 ++-- .../script/context/PluginScriptContext.java | 23 +++++++++--------- .../plugin/script/context/ScriptContext.java | 4 +++- .../script/engine/AbstractScriptEngine.java | 2 +- .../plugin/script/engine/JsScriptEngine.java | 24 +++++++++---------- .../script/engine/ScriptEngineFactory.java | 13 +++++----- .../iot/plugin/script/sandbox/JsSandbox.java | 20 +++++++++------- .../plugin/script/sandbox/ScriptSandbox.java | 3 ++- .../plugin/script/service/ScriptService.java | 11 +++++---- .../script/service/ScriptServiceImpl.java | 12 ++++++++-- .../iot/plugin/script/util/ScriptUtils.java | 17 +++++++++---- 20 files changed, 111 insertions(+), 75 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptLanguageEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptLanguageEnum.java index cc1d751918..92e5d2cfb8 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptLanguageEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptLanguageEnum.java @@ -43,4 +43,5 @@ public enum IotProductScriptLanguageEnum implements ArrayValuable { .findFirst() .orElse(null); } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptStatusEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptStatusEnum.java index 086d84faa5..f9036bedf0 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptStatusEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductScriptStatusEnum.java @@ -6,6 +6,7 @@ import lombok.Getter; import java.util.Arrays; +// TODO @haohao:要不复用 commonstatus? /** * IoT 产品脚本状态枚举 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductScriptDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductScriptDO.java index 6b973e6529..64cab3ce95 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductScriptDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductScriptDO.java @@ -8,6 +8,7 @@ import lombok.*; import java.time.LocalDateTime; +// TODO @haohao:类似阿里云的脚本,貌似是一个?这个可以简化么?【微信讨论哈】类似阿里云,貌似是加了个 topic? /** * IoT 产品脚本信息 DO * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductScriptServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductScriptServiceImpl.java index 99638785d8..d15569748e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductScriptServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductScriptServiceImpl.java @@ -26,6 +26,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS; import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_SCRIPT_NOT_EXISTS; +// TODO @芋艿:后续再 review 哈! /** * IoT 产品脚本信息 Service 实现类 * diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/IotHttpPluginApplication.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/IotHttpPluginApplication.java index d569ba3b83..07d4a4790e 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/IotHttpPluginApplication.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/IotHttpPluginApplication.java @@ -5,17 +5,15 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; +// TODO @芋艿:是不是搞成 cn.iocoder.yudao.module.iot.plugin?或者 common、script 要自动配置 /** * 独立运行入口 */ @Slf4j @SpringBootApplication(scanBasePackages = { - // common 的包 - "cn.iocoder.yudao.module.iot.plugin.common", - // http 的包 - "cn.iocoder.yudao.module.iot.plugin.http", - // script 的包 - "cn.iocoder.yudao.module.iot.plugin.script" + "cn.iocoder.yudao.module.iot.plugin.common", // common 的包 + "cn.iocoder.yudao.module.iot.plugin.http", // http 的包 + "cn.iocoder.yudao.module.iot.plugin.script" // script 的包 }) public class IotHttpPluginApplication { diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/script/HttpScriptService.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/script/HttpScriptService.java index 18a7731acc..0312cba22f 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/script/HttpScriptService.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/script/HttpScriptService.java @@ -13,7 +13,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * HTTP协议脚本处理服务 + * HTTP 协议脚本处理服务 * 用于管理和执行设备数据解析脚本 * * @author haohao @@ -25,8 +25,10 @@ public class HttpScriptService { private final ScriptService scriptService; + // TODO @haohao:后续可以考虑放到 guava 缓存 + // TODO @haohao:可能要抽一个 script factory 之类的?方便多个 emqx、http 之类复用? /** - * 脚本缓存,按产品Key缓存脚本内容 + * 脚本缓存,按产品 Key 缓存脚本内容 */ private final Map scriptCache = new ConcurrentHashMap<>(); @@ -76,6 +78,7 @@ public class HttpScriptService { productKey, deviceName, e); } + // TODO @芋艿:解析失败,是不是不能返回空?! // 解析失败,返回空数据 return new HashMap<>(); } @@ -115,13 +118,14 @@ public class HttpScriptService { productKey, deviceName, identifier, payload, result); // 处理结果 + // TODO @haohao:处理结果,可以复用么? if (result instanceof Map) { return (Map) result; } else if (result instanceof String) { try { return new JsonObject((String) result).getMap(); } catch (Exception e) { - log.warn("[parseEventData][脚本返回的字符串不是有效的JSON] result:{}", result); + log.warn("[parseEventData][脚本返回的字符串不是有效的 JSON] result:{}", result); } } } catch (Exception e) { @@ -129,6 +133,7 @@ public class HttpScriptService { productKey, deviceName, identifier, e); } + // TODO @芋艿:解析失败,是不是不能返回空?! // 解析失败,返回空数据 return new HashMap<>(); } @@ -191,10 +196,11 @@ public class HttpScriptService { /** * 设置产品解析脚本 * - * @param productKey 产品Key + * @param productKey 产品 Key * @param script 脚本内容 */ public void setScript(String productKey, String script) { + // TODO @haohao:if return 会好点哈 if (StrUtil.isNotBlank(productKey) && StrUtil.isNotBlank(script)) { // 验证脚本是否有效 if (scriptService.validateScript("js", script)) { @@ -209,13 +215,14 @@ public class HttpScriptService { /** * 清除产品解析脚本 * - * @param productKey 产品Key + * @param productKey 产品 Key */ public void clearScript(String productKey) { - if (StrUtil.isNotBlank(productKey)) { - scriptCache.remove(productKey); - log.info("[clearScript][清除产品:{}的解析脚本]", productKey); + if (StrUtil.isBlank(productKey)) { + return; } + scriptCache.remove(productKey); + log.info("[clearScript][清除产品({})的解析脚本]", productKey); } /** @@ -225,4 +232,5 @@ public class HttpScriptService { scriptCache.clear(); log.info("[clearAllScripts][清除所有脚本缓存]"); } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java index 3752a112b9..5a0257cac6 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java @@ -35,8 +35,7 @@ public class IotDeviceUpstreamServer { router.route().handler(BodyHandler.create()); // 处理 Body // 使用统一的 Handler 处理所有上行请求 - IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler(deviceUpstreamApi, - applicationContext); + IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler(deviceUpstreamApi, applicationContext); router.post(IotDeviceUpstreamVertxHandler.PROPERTY_PATH).handler(upstreamHandler); router.post(IotDeviceUpstreamVertxHandler.EVENT_PATH).handler(upstreamHandler); diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java index c161c3312f..2aec09425b 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.plugin.http.upstream.router; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -150,10 +151,11 @@ public class IotDeviceUpstreamVertxHandler implements Handler { Map properties = scriptService.parsePropertyData(productKey, deviceName, body); // 如果脚本解析结果为空,使用默认解析逻辑 - if (properties.isEmpty()) { + // TODO @芋艿:注释说明一下,为什么要这么处理? + if (CollUtil.isNotEmpty(properties)) { properties = new HashMap<>(); - Map params = body.getJsonObject("params") != null ? body.getJsonObject("params").getMap() - : null; + Map params = body.getJsonObject("params") != null ? + body.getJsonObject("params").getMap() : null; if (params != null) { // 将标准格式的 params 转换为平台需要的 properties 格式 for (Map.Entry entry : params.entrySet()) { @@ -193,7 +195,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler { Map params = scriptService.parseEventData(productKey, deviceName, identifier, body); // 如果脚本解析结果为空,使用默认解析逻辑 - if (params.isEmpty()) { + if (CollUtil.isNotEmpty(params)) { if (body.containsKey("params")) { params = body.getJsonObject("params").getMap(); } else { diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/ScriptExample.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/ScriptExample.java index 19cfc34a0f..b72165cc70 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/ScriptExample.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/ScriptExample.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; +// TODO @haohao:写到单测类里; /** * 脚本使用示例类 */ diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/config/ScriptConfiguration.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/config/ScriptConfiguration.java index 7f79240b1f..511ca8bc54 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/config/ScriptConfiguration.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/config/ScriptConfiguration.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.iot.plugin.script.service.ScriptServiceImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +// TODO @haohao:这个模块,是不是融合到 plugin-common 里哈? /** * 脚本模块配置类 */ @@ -31,7 +32,7 @@ public class ScriptConfiguration { @Bean public ScriptService scriptService(ScriptEngineFactory engineFactory) { ScriptServiceImpl service = new ScriptServiceImpl(); - // 如果有其他配置可以在这里设置 + // TODO @haohao:如果有其他配置可以在这里设置 return service; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/PluginScriptContext.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/PluginScriptContext.java index 4bee8d0259..27956453d8 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/PluginScriptContext.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/PluginScriptContext.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.iot.plugin.script.context; +import lombok.Getter; + import java.util.HashMap; import java.util.Map; @@ -11,18 +13,22 @@ public class PluginScriptContext implements ScriptContext { /** * 上下文参数 */ + @Getter private final Map parameters = new HashMap<>(); /** * 上下文函数 */ + @Getter private final Map functions = new HashMap<>(); /** * 日志函数接口 */ public interface LogFunction { + void log(String message); + } /** @@ -46,16 +52,6 @@ public class PluginScriptContext implements ScriptContext { } } - @Override - public Map getParameters() { - return parameters; - } - - @Override - public Map getFunctions() { - return functions; - } - @Override public void setParameter(String key, Object value) { parameters.put(key, value); @@ -71,6 +67,7 @@ public class PluginScriptContext implements ScriptContext { functions.put(name, function); } + // TODO @haohao:setParameters?这样的话,with 都是一些比较个性的参数 /** * 批量设置参数 * @@ -87,11 +84,13 @@ public class PluginScriptContext implements ScriptContext { /** * 添加设备相关的上下文参数 * - * @param deviceId 设备ID + * @param deviceId 设备 ID * @param deviceData 设备数据 * @return 当前上下文对象 */ + // TODO @haohao:是不是加个 (String productKey, String deviceName, Map deviceData) { public PluginScriptContext withDeviceContext(String deviceId, Map deviceData) { + // TODO @haohao:deviceId 一般是分开,还是合并哈? parameters.put("deviceId", deviceId); parameters.put("deviceData", deviceData); return this; @@ -110,6 +109,7 @@ public class PluginScriptContext implements ScriptContext { return this; } + // TODO @haohao:setParameter 可以融合哈? /** * 设置单个参数 * @@ -121,4 +121,5 @@ public class PluginScriptContext implements ScriptContext { parameters.put(key, value); return this; } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/ScriptContext.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/ScriptContext.java index 7f41855fd4..e165bf5afa 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/ScriptContext.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/ScriptContext.java @@ -37,6 +37,7 @@ public interface ScriptContext { */ Object getParameter(String key); + // TODO @haohao:这个要不也是 setFunction /** * 注册函数 * @@ -44,4 +45,5 @@ public interface ScriptContext { * @param function 函数对象 */ void registerFunction(String name, Object function); -} \ No newline at end of file + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/AbstractScriptEngine.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/AbstractScriptEngine.java index 3401c0cf5b..4549242eef 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/AbstractScriptEngine.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/AbstractScriptEngine.java @@ -48,4 +48,4 @@ public abstract class AbstractScriptEngine { public void setSandbox(ScriptSandbox sandbox) { this.sandbox = sandbox; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/JsScriptEngine.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/JsScriptEngine.java index 484ad0b0fb..69ec5cfc20 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/JsScriptEngine.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/JsScriptEngine.java @@ -12,8 +12,8 @@ import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; /** - * JavaScript脚本引擎实现 - * 使用JSR-223 Nashorn脚本引擎 + * JavaScript 脚本引擎实现 + * 使用 JSR-223 Nashorn 脚本引擎 */ @Slf4j public class JsScriptEngine extends AbstractScriptEngine { @@ -24,7 +24,7 @@ public class JsScriptEngine extends AbstractScriptEngine { private static final long DEFAULT_TIMEOUT_MS = 5000; /** - * JavaScript引擎名称 + * JavaScript 引擎名称 */ private static final String JS_ENGINE_NAME = "nashorn"; @@ -45,25 +45,24 @@ public class JsScriptEngine extends AbstractScriptEngine { @Override public void init() { - log.info("初始化JavaScript脚本引擎"); + log.info("初始化 JavaScript 脚本引擎"); // 创建脚本引擎管理器 engineManager = new ScriptEngineManager(); - // 获取JavaScript引擎 + // 获取 JavaScript 引擎 engine = engineManager.getEngineByName(JS_ENGINE_NAME); if (engine == null) { - log.error("无法创建JavaScript引擎,尝试使用JavaScript名称获取"); + log.error("无法创建JavaScript引擎,尝试使用 JavaScript 名称获取"); engine = engineManager.getEngineByName("JavaScript"); } - if (engine == null) { - throw new IllegalStateException("无法创建JavaScript引擎,请检查环境配置"); + throw new IllegalStateException("无法创建 JavaScript 引擎,请检查环境配置"); } log.info("成功创建JavaScript引擎: {}", engine.getClass().getName()); - // 默认使用JS沙箱 + // 默认使用 JS 沙箱 if (sandbox == null) { setSandbox(new JsSandbox()); } @@ -99,7 +98,7 @@ public class JsScriptEngine extends AbstractScriptEngine { // 执行脚本 return engine.eval(script, bindings); } catch (ScriptException e) { - log.error("执行JavaScript脚本异常: {}", e.getMessage()); + log.error("执行 JavaScript 脚本异常: {}", e.getMessage()); throw new RuntimeException("脚本执行异常: " + e.getMessage(), e); } }; @@ -136,7 +135,7 @@ public class JsScriptEngine extends AbstractScriptEngine { // 执行脚本 return engine.eval(script, bindings); } catch (ScriptException e) { - log.error("执行JavaScript脚本异常: {}", e.getMessage()); + log.error("执行 JavaScript 脚本异常: {}", e.getMessage()); throw new RuntimeException("脚本执行异常: " + e.getMessage(), e); } }; @@ -152,9 +151,10 @@ public class JsScriptEngine extends AbstractScriptEngine { @Override public void destroy() { - log.info("销毁JavaScript脚本引擎"); + log.info("销毁 JavaScript 脚本引擎"); cachedScripts.clear(); engine = null; engineManager = null; } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/ScriptEngineFactory.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/ScriptEngineFactory.java index d0c8f6d1bc..e5c653512f 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/ScriptEngineFactory.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/ScriptEngineFactory.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.plugin.script.engine; +import cn.hutool.core.lang.Assert; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -11,12 +12,12 @@ import org.springframework.stereotype.Component; public class ScriptEngineFactory { /** - * 创建JavaScript脚本引擎 + * 创建 JavaScript 脚本引擎 * * @return JavaScript脚本引擎 */ public JsScriptEngine createJsEngine() { - log.debug("创建JavaScript脚本引擎"); + log.debug("创建 JavaScript 脚本引擎"); return new JsScriptEngine(); } @@ -27,10 +28,7 @@ public class ScriptEngineFactory { * @return 脚本引擎 */ public AbstractScriptEngine createEngine(String scriptType) { - if (scriptType == null || scriptType.isEmpty()) { - throw new IllegalArgumentException("脚本类型不能为空"); - } - + Assert.notBlank(scriptType, "脚本类型不能为空"); switch (scriptType.toLowerCase()) { case "js": case "javascript": @@ -40,4 +38,5 @@ public class ScriptEngineFactory { throw new IllegalArgumentException("不支持的脚本类型: " + scriptType); } } -} \ No newline at end of file + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/JsSandbox.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/JsSandbox.java index 2e6d6b7aa8..aeb1f0ccac 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/JsSandbox.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/JsSandbox.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.plugin.script.sandbox; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import javax.script.ScriptEngine; @@ -8,8 +9,9 @@ import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; +// TODO @haohao:这个是不是融合到 ScriptEngine 里 /** - * JavaScript脚本沙箱,限制脚本的执行权限 + * JavaScript 脚本沙箱,限制脚本的执行权限 */ @Slf4j public class JsSandbox implements ScriptSandbox { @@ -34,6 +36,7 @@ public class JsSandbox implements ScriptSandbox { "(?:\\bchild_process\\b)|" + "(?:\\bwindow\\b)"); + // TODO @haohao:这个没用到哈。 /** * 脚本执行超时时间(毫秒) */ @@ -44,30 +47,28 @@ public class JsSandbox implements ScriptSandbox { if (!(engineContext instanceof ScriptEngine)) { throw new IllegalArgumentException("引擎上下文类型不正确,无法应用JavaScript沙箱"); } - ScriptEngine engine = (ScriptEngine) engineContext; - // 在Nashorn引擎中,可以通过以下方式设置安全限制 + // 在 Nashorn 引擎中,可以通过以下方式设置安全限制 try { // 设置严格模式 String securityPrefix = "'use strict';\n"; - // 禁用Java.type等访问系统资源的功能 + // 禁用 Java.type 等访问系统资源的功能 engine.eval("var Java = undefined;"); engine.eval("var JavaImporter = undefined;"); engine.eval("var Packages = undefined;"); // 增强安全控制可以在这里添加 - log.debug("已应用JavaScript安全沙箱限制"); - + log.debug("已应用 JavaScript 安全沙箱限制"); } catch (Exception e) { - log.warn("应用JavaScript沙箱限制失败: {}", e.getMessage()); + log.warn("应用 JavaScript 沙箱限制失败: {}", e.getMessage()); } } @Override public boolean validateScript(String script) { - if (script == null || script.isEmpty()) { + if (StrUtil.isNotEmpty(script)) { return false; } @@ -86,11 +87,12 @@ public class JsSandbox implements ScriptSandbox { } // 脚本长度限制 - if (script.length() > 1024 * 100) { // 限制100KB + if (script.length() > 1024 * 100) { // 限制 100 KB log.warn("脚本太大,超过了限制"); return false; } return true; } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/ScriptSandbox.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/ScriptSandbox.java index cd8d9cd505..2c31a32041 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/ScriptSandbox.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/sandbox/ScriptSandbox.java @@ -20,4 +20,5 @@ public interface ScriptSandbox { * @return 是否安全 */ boolean validateScript(String script); -} \ No newline at end of file + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptService.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptService.java index 70b3223fc4..0802d62413 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptService.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptService.java @@ -12,7 +12,7 @@ public interface ScriptService { /** * 执行脚本 * - * @param scriptType 脚本类型(如js、groovy等) + * @param scriptType 脚本类型(如 js、groovy 等) * @param script 脚本内容 * @param context 脚本上下文 * @return 脚本执行结果 @@ -22,7 +22,7 @@ public interface ScriptService { /** * 执行脚本 * - * @param scriptType 脚本类型(如js、groovy等) + * @param scriptType 脚本类型(如 js、groovy 等) * @param script 脚本内容 * @param params 脚本参数 * @return 脚本执行结果 @@ -30,7 +30,7 @@ public interface ScriptService { Object executeScript(String scriptType, String script, Map params); /** - * 执行JavaScript脚本 + * 执行 JavaScript 脚本 * * @param script 脚本内容 * @param context 脚本上下文 @@ -39,7 +39,7 @@ public interface ScriptService { Object executeJavaScript(String script, ScriptContext context); /** - * 执行JavaScript脚本 + * 执行 JavaScript 脚本 * * @param script 脚本内容 * @param params 脚本参数 @@ -55,4 +55,5 @@ public interface ScriptService { * @return 脚本是否安全 */ boolean validateScript(String scriptType, String script); -} \ No newline at end of file + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptServiceImpl.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptServiceImpl.java index cf2e40e6ef..e1bf862d15 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/service/ScriptServiceImpl.java @@ -38,6 +38,7 @@ public class ScriptServiceImpl implements ScriptService { @PostConstruct public void init() { // 初始化常用的脚本引擎和沙箱 + // TODO @haohao:js 是不是要枚举下哈。 getEngine("js"); sandboxCache.put("js", new JsSandbox()); } @@ -49,6 +50,7 @@ public class ScriptServiceImpl implements ScriptService { try { engine.destroy(); } catch (Exception e) { + // TODO @haohao:engine 类名 log.error("销毁脚本引擎失败", e); } } @@ -58,6 +60,7 @@ public class ScriptServiceImpl implements ScriptService { @Override public Object executeScript(String scriptType, String script, ScriptContext context) { + // TODO @haohao:可以使用 hutool assert if (scriptType == null || script == null) { throw new IllegalArgumentException("脚本类型和内容不能为空"); } @@ -74,6 +77,7 @@ public class ScriptServiceImpl implements ScriptService { // 执行脚本 return engine.execute(script, context); } catch (Exception e) { + // TODO @haohao:最好把 e 堆栈出来哈;然后,engine 类名 log.error("执行脚本失败: {}", e.getMessage()); throw new RuntimeException("执行脚本失败: " + e.getMessage(), e); } @@ -83,16 +87,19 @@ public class ScriptServiceImpl implements ScriptService { public Object executeScript(String scriptType, String script, Map params) { // 创建默认上下文 ScriptContext context = new PluginScriptContext(params); + // 执行脚本 return executeScript(scriptType, script, context); } @Override public Object executeJavaScript(String script, ScriptContext context) { + // TODO @haohao:枚举哈 return executeScript("js", script, context); } @Override public Object executeJavaScript(String script, Map params) { + // TODO @haohao:枚举哈 return executeScript("js", script, params); } @@ -100,7 +107,8 @@ public class ScriptServiceImpl implements ScriptService { public boolean validateScript(String scriptType, String script) { ScriptSandbox sandbox = sandboxCache.get(scriptType.toLowerCase()); if (sandbox == null) { - log.warn("找不到脚本类型[{}]对应的沙箱,使用默认JS沙箱", scriptType); + // TODO @haohao:疑问,为啥默认 JsSandbox 哈? + log.warn("[validateScript][找不到脚本类型[{}]对应的沙箱,使用默认 JS 沙箱]", scriptType); sandbox = new JsSandbox(); sandboxCache.put(scriptType.toLowerCase(), sandbox); } @@ -120,4 +128,4 @@ public class ScriptServiceImpl implements ScriptService { return engine; }); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/util/ScriptUtils.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/util/ScriptUtils.java index 739d4b23c6..b14eb772f7 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/util/ScriptUtils.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/util/ScriptUtils.java @@ -6,6 +6,9 @@ import lombok.extern.slf4j.Slf4j; import java.util.Map; import java.util.concurrent.*; +// TODO @haohao:【重要】 ScriptUtil.createGroovyEngine() 可以服用 hutool 的封装么? +// TODO @haohao:【重要】 js 引擎,可能要看下 jdk8 的兼容性; +// TODO @haohao:【重要】我们要不 script 配置的时候,支持 scriptType?!感觉会更通用一些???groovy、python、js /** * 脚本工具类,提供执行脚本的辅助方法 */ @@ -66,6 +69,7 @@ public class ScriptUtils { * 关闭工具类的线程池 */ public static void shutdown() { + // TODO @芋艿:有没默认工具类,可以 shutdown SCRIPT_EXECUTOR.shutdown(); try { if (!SCRIPT_EXECUTOR.awaitTermination(10, TimeUnit.SECONDS)) { @@ -77,8 +81,9 @@ public class ScriptUtils { } } + // TODO @芋艿:要不要使用 JsonUtils /** - * 将JSON字符串转换为Map + * 将 JSON 字符串转换为 Map * * @param json JSON字符串 * @return Map对象,转换失败则返回null @@ -86,19 +91,20 @@ public class ScriptUtils { @SuppressWarnings("unchecked") public static Map parseJson(String json) { try { - // 使用hutool的JSONUtil工具类解析JSON return JSONUtil.toBean(json, Map.class); } catch (Exception e) { - log.error("解析JSON失败: {}", e.getMessage()); + // TODO @haohao:json、e 都打印出来哈 + log.error("[parseJson][解析JSON失败: {}]", e.getMessage()); return null; } } + // TODO @芋艿:要不要封装成 utils /** * 尝试将对象转换为整数 * * @param obj 需要转换的对象 - * @return 转换后的整数,如果无法转换则返回null + * @return 转换后的整数,如果无法转换则返回 null */ public static Integer toInteger(Object obj) { if (obj == null) { @@ -122,6 +128,7 @@ public class ScriptUtils { return null; } + // TODO @芋艿:要不要封装成 utils /** * 尝试将对象转换为双精度浮点数 * @@ -158,10 +165,12 @@ public class ScriptUtils { * @return 如果两个数值相等则返回true,否则返回false */ public static boolean numbersEqual(Number a, Number b) { + // TODO @haohao:NumberUtil.equals(1, 1D) if (a == null || b == null) { return a == b; } return Math.abs(a.doubleValue() - b.doubleValue()) < 0.0000001; } + } \ No newline at end of file