tio-boot 与 magic-script 集成指南
本指南演示如何在基于 JVM 的动态脚本框架 magic-script 中,快速集成并在 tio-boot 项目中执行脚本。
1. 概述
magic-script
是一个基于 JVM 的动态脚本引擎,支持类似 JavaScript 的语法,并且可以方便地与 Java 应用集成。通过将脚本与 tio-boot Web 服务结合,可以在运行时动态加载并执行脚本文件,从而实现灵活的业务扩展和热部署。
本示例代码已开源,仓库地址:
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
相关依赖:
<properties>
<java.version>1.8</java.version>
<tio-boot.version>1.9.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>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>${tio-boot.version}</version>
</dependency>
<!-- 热加载支持(可选) -->
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>hotswap-classloader</artifactId>
<version>1.2.6</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.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
工具类,用于加载并执行脚本:
package com.litongjava.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 com.litongjava.tio.utils.hutool.FileUtil;
import com.litongjava.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
中:
// helloworld.ms
var sql = """select * from test_data""";
println(sql);
return "hello";
编写 ScriptRunner
类测试脚本:
package com.litongjava.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 路由功能,可在收到请求时执行脚本:
- 在
src/main/resources/ms/web_hello.ms
编写请求处理脚本:
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.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;
- 在配置类中注册 HTTP 路由:
package com.litongjava.tio.web.hello.config;
import com.litongjava.annotation.AConfiguration;
import com.litongjava.annotation.Initialization;
import com.litongjava.magic.script.ScriptManager;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.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");
});
}
}
- 启动 tio-boot 应用,访问
http://localhost:8080/hi
,将得到类似如下的 JSON 响应:
{
"data": { "sql": "select * from test_data where name=?" },
"ok": true,
"code": 1
}
7. 查询数据库
import com.litongjava.tio.http.common.HttpRequest
import com.litongjava.tio.http.common.HttpResponse
import com.litongjava.tio.boot.http.TioRequestContext
import com.litongjava.model.body.RespBodyVo
import com.jfinal.kit.Kv
import com.litongjava.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 路由中动态加载并执行脚本文件
这种方式不仅便于热部署业务逻辑,还能让业务人员以脚本形式快速迭代、调试,提高开发效率。
参考链接
- magic-script 官方文档: https://www.ssssssss.org/magic-api/pages/base/script/
- tio-boot 项目: https://github.com/litongjava/tio-boot