Skip to content

tio-boot 与 magic-script 集成指南 ​

本指南演示如何在基于 JVM 的动态脚本框架 magic-script 中,快速集成并在 tio-boot 项目中执行脚本。


1. 概述 ​

magic-script 是一个基于 JVM 的动态脚本引擎,支持类似 JavaScript 的语法,并且可以方便地与 Java 应用集成。通过将脚本与 tio-boot Web 服务结合,可以在运行时动态加载并执行脚本文件,从而实现灵活的业务扩展和热部署。

本示例代码已开源,仓库地址:

https://github.com/litongjava/java-ee-tio-boot-study/tree/main/tio-boot-latest-study/tio-boot-magic-script-study


tio-boot 与 magic-script 集成指南 ​

1. 简介 ​

文档介绍

  • 如何执行magic script脚本
  • 如何使用magic script脚本返回http响应
  • 如何使用magic script查询数据并返回http响应

2. 环境准备 ​

  • Java 1.8
  • Maven
  • tio-boot 版本:1.9.8
  • magic-script 版本:1.8.8

3. 添加依赖 ​

在 pom.xml 中,声明 magic-script 与 tio-boot 相关依赖:

xml
<properties>
  <java.version>1.8</java.version>
  <tio-boot.version>2.1.8</tio-boot.version>
  <magic-script.version>1.8.8</magic-script.version>
</properties>

<dependencies>
  <!-- JSON 解析 -->
  <dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.12</version>
  </dependency>

  <!-- magic-script 引擎 -->
  <dependency>
    <groupId>org.ssssssss</groupId>
    <artifactId>magic-script</artifactId>
    <version>${magic-script.version}</version>
  </dependency>

  <!-- tio-boot 核心 -->
  <dependency>
    <groupId>nexus.io</groupId>
    <artifactId>tio-boot</artifactId>
    <version>${tio-boot.version}</version>
  </dependency>

  <!-- 热加载支持(可选) -->
  <dependency>
    <groupId>nexus.io</groupId>
    <artifactId>hotswap-classloader</artifactId>
    <version>1.2.6</version>
  </dependency>

  <!-- 日志 -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.3.3</version>
  </dependency>

  <!-- Lombok(开发时) -->
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
  </dependency>

  <!-- 测试框架 -->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
  </dependency>
</dependencies>

4. 编写脚本执行工具类 ​

创建 ScriptManager 工具类,用于加载并执行脚本:

java
package nexus.io.magic.script;

import java.net.URL;
import java.nio.charset.StandardCharsets;
import org.ssssssss.script.MagicScript;
import org.ssssssss.script.MagicScriptContext;
import org.ssssssss.script.MagicScriptDebugContext;
import nexus.io.tio.utils.hutool.FileUtil;
import nexus.io.tio.utils.hutool.ResourceUtil;

public class ScriptManager {

  /**
   * 执行脚本内容
   */
  public static Object executeScript(String script, MagicScriptContext context) {
    // 若是调试模式,添加 DEBUG_MARK
    script = (context instanceof MagicScriptDebugContext ? MagicScript.DEBUG_MARK : "") + script;
    MagicScript magicScript = MagicScript.create(script, null);
    return magicScript.execute(context);
  }

  /**
   * 从 classpath 加载并执行脚本文件
   */
  @SuppressWarnings("unchecked")
  public static <T> T executeClasspathScript(String filename) throws Exception {
    URL resource = ResourceUtil.getResource(filename);
    byte[] bytes = FileUtil.readBytes(FileUtil.file(resource.getFile()));
    String script = new String(bytes, StandardCharsets.UTF_8);
    MagicScriptContext context = new MagicScriptContext();
    return (T) executeScript(script, context);
  }
}
  • executeScript:接收脚本字符串与上下文,创建并执行。
  • executeClasspathScript:从资源路径读取脚本文件,转换为字符串后调用 executeScript。

5. 运行独立脚本示例 ​

在 src/main/resources/ms/helloworld.ms 中:

js
// helloworld.ms
var sql = """select * from test_data""";
println(sql);
return "hello";

编写 ScriptRunner 类测试脚本:

java
package nexus.io.magic.script;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import org.ssssssss.script.MagicScriptContext;

public class ScriptRunner {
  public static void main(String[] args) {
    try {
      Path path = Paths.get("src/main/resources/ms/helloworld.ms");
      String script = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
      MagicScriptContext context = new MagicScriptContext();
      Object result = ScriptManager.executeScript(script, context);
      System.out.println("脚本返回:" + result);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

运行后将输出:

select * from test_data
脚本返回:hello

6. 在 Web 服务中集成脚本 ​

借助 tio-boot 提供的 HTTP 路由功能,可在收到请求时执行脚本:

  1. 在 src/main/resources/ms/web_hello.ms 编写请求处理脚本:
js
import nexus.io.tio.boot.http.TioRequestContext;
import nexus.io.model.body.RespBodyVo;
import com.jfinal.kit.Kv;

var request = TioRequestContext.getRequest();
var response = TioRequestContext.getResponse();

var sql = """select * from test_data where name=?""";
var kv = Kv.by("sql", sql);

var respBodyVo = RespBodyVo.ok(kv);
response.setJson(respBodyVo);
return response;
  1. 在配置类中注册 HTTP 路由:
java
package nexus.io.tio.web.hello.config;

import nexus.io.annotation.AConfiguration;
import nexus.io.annotation.Initialization;
import nexus.io.magic.script.ScriptManager;
import nexus.io.tio.boot.server.TioBootServer;
import nexus.io.tio.http.server.router.HttpRequestRouter;

@AConfiguration
public class RequestHandlerConfig {

  @Initialization
  public void httpRoutes() {
    HttpRequestRouter router = TioBootServer.me().getRequestRouter();
    router.add("/hi", request -> {
      return ScriptManager.executeClasspathScript("ms/web_hello.ms");
    });
  }
}
  1. 启动 tio-boot 应用,访问 http://localhost:8080/hi,将得到类似如下的 JSON 响应:
json
{
  "data": { "sql": "select * from test_data where name=?" },
  "ok": true,
  "code": 1
}

7. 查询数据库 ​

import nexus.io.tio.http.common.HttpRequest
import nexus.io.tio.http.common.HttpResponse
import nexus.io.tio.boot.http.TioRequestContext
import nexus.io.model.body.RespBodyVo
import com.jfinal.kit.Kv
import nexus.io.db.activerecord.Db

//调用静态方法
var request=TioRequestContext.getRequest();
var response=TioRequestContext.getResponse();


var sql = """select 1"""
println(sql)

var row=Db.findFirt(sql)
println(row.toKv())

var respBodyVo=RespBodyVo.ok(row.toKv())
response.setJson(respBodyVo)
return response;

3. 小结 ​

通过上述步骤,我们演示了如何:

  • 在 Maven 项目中添加 magic-script 与 tio-boot 依赖
  • 编写通用脚本执行工具类 ScriptManager
  • 在控制台与独立测试类中运行脚本
  • 在 tio-boot Web 路由中动态加载并执行脚本文件

这种方式不仅便于热部署业务逻辑,还能让业务人员以脚本形式快速迭代、调试,提高开发效率。


参考链接 ​

MIT Licensed