tio-boot 整合 magic-script

magic-script 简介

magic-script 是基于 jvm 的动态脚本语言https://www.ssssssss.org/magic-api/pages/base/script/

tio-boot 整合 magic-script

1.添加依赖 添加 magic-script 依赖

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

完整的依赖如下

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <java.version>1.8</java.version>
  <maven.compiler.source>${java.version}</maven.compiler.source>
  <maven.compiler.target>${java.version}</maven.compiler.target>
  <graalvm.version>23.1.1</graalvm.version>
  <tio-boot.version>1.5.2</tio-boot.version>
  <lombok-version>1.18.30</lombok-version>
  <hotswap-classloader.version>1.2.2</hotswap-classloader.version>
  <magic-script.version>1.8.8</magic-script.version>
  <final.name>web-hello</final.name>
  <main.class>com.litongjava.tio.web.hello.HelloApp</main.class>
</properties>
<dependencies>

  <dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.12</version>
  </dependency>

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


  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
  </dependency>

  <dependency>
    <groupId>com.litongjava</groupId>
    <artifactId>tio-boot</artifactId>
    <version>${tio-boot.version}</version>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok-version}</version>
    <optional>true</optional>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>com.litongjava</groupId>
    <artifactId>hotswap-classloader</artifactId>
    <version>${hotswap-classloader.version}</version>
  </dependency>

  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
  </dependency>

</dependencies>

添加工具类 创建了一个名为 ScriptManager 的工具类,这个类包含两个方法:executeScriptexecuteClasspathScript

  • executeScript(String script, MagicScriptContext context):这个方法通过传入的脚本字符串和上下文对象来执行脚本。它首先检查上下文是否为调试模式,然后创建并执行脚本。
  • executeClasspathScript(String filename):这个方法读取类路径下的脚本文件,转换为字符串,并执行它。这对于从资源文件夹中加载和执行脚本非常有用。
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) {
    script = (context instanceof MagicScriptDebugContext ? MagicScript.DEBUG_MARK : "") + script;
    MagicScript magicScript = MagicScript.create(script, null);
    // 执行脚本
    return magicScript.execute(context);
  }

  /**
   * 执行class-path下的脚步
   */
  @SuppressWarnings("unchecked")
  public static <T> T executeClasspathScript(String filename) throws Exception {
    // 读取脚本文件
    URL resource = ResourceUtil.getResource(filename);
    java.io.File file = FileUtil.file(resource.getFile());
    byte[] bytes = FileUtil.readBytes(file);
    String script = new String(bytes, StandardCharsets.UTF_8);

    // 创建脚本上下文
    MagicScriptContext context = new MagicScriptContext();

    // 执行脚本
    Object result = ScriptManager.executeScript(script, context);

    return (T) result;
  }
}

1.3.运行一个脚本 创建 magic-script 脚本文件 src\main\resources\ms\helloworld.ms

var sql = """select * from test_data"""
println(sql)
return """hello"""

如何通过代码运行 src\main\resources\ms\helloworld.ms

使用 Java 代码运行脚本 创建了一个 ScriptRunner 类,其中的 main 方法用于从资源文件 helloworld.ms 中读取脚本并执行。这个脚本包含一个 SQL 语句和一个打印语句,并返回一个字符串 "hello"。

package com.litongjava.magic.script;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.ssssssss.script.MagicScriptContext;

public class ScriptRunner {

  public static void main(String[] args) {
    // 设置文件路径
    Path path = Paths.get("src/main/resources/ms/helloworld.ms");

    try {
      // 读取脚本文件
      byte[] bytes = Files.readAllBytes(path);
      String script = new String(bytes, StandardCharsets.UTF_8);

      // 创建脚本上下文
      MagicScriptContext context = new MagicScriptContext();

      // 执行脚本
      Object result = ScriptManager.executeScript(script, context);
      System.out.println(result);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

1.4.整合 web 请求 如何在 Web 服务中使用 Magic Script 来处理 HTTP 请求。这涉及到几个步骤:

  • 脚本文件 web_hello.ms:包含用于 Web 请求的脚本,它从 TioControllerContext 获取 HTTP 请求和响应对象,设置 JSON 响应并返回。
  • 配置类 HttpServerRequestHanlderConfig:在这个类中,你通过使用 SimpleHttpRoutes 来添加一个路由 "/hi",该路由关联到 web_hello.ms 脚本。这样,每当有 HTTP 请求到这个路由时,就会执行对应的脚本。

处理流程

  1. Web 请求到达:当一个 HTTP 请求到达路由 "/hi" 时,路由处理函数被触发。
  2. 执行脚本:路由处理函数调用 ScriptManager.executeClasspathScript 来执行 web_hello.ms 脚本。
  3. 脚本处理:脚本从 Tio 框架的上下文中获取请求和响应对象,执行数据库查询,然后设置响应对象的 JSON 格式,并返回这个响应对象。
  4. 返回响应:最终,响应对象被转换为 JSON 格式并发送回客户端。

src\main\resources\ms\web_hello.ms

import com.litongjava.tio.http.common.HttpRequest
import com.litongjava.tio.http.common.HttpResponse
import com.litongjava.tio.boot.http.TioControllerContext
import com.litongjava.tio.utils.resp.RespVo

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


var sql = """select * from test_data where name=?"""
println(sql)

response.setJson(RespVo.ok(sql))
return response;

添加 handler

HttpServerRequestHanlderConfig

package com.litongjava.tio.web.hello.config;

import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.jfinal.aop.annotation.BeforeStartConfiguration;
import com.litongjava.magic.script.ScriptManager;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.http.server.handler.SimpleHttpRoutes;

@BeforeStartConfiguration
public class HttpServerRequestHanlderConfig {

  @AInitialization
  public void httpRoutes() {

    // 创建simpleHttpRoutes
    SimpleHttpRoutes simpleHttpRoutes = new SimpleHttpRoutes();

    simpleHttpRoutes.add("/hi", (request) -> {
      String filename = "ms/web_hello.ms";
      return ScriptManager.executeClasspathScript(filename);

    });

    // 将simpleHttpRoutes添加到TioBootServer
    TioBootServer.me().setHttpRoutes(simpleHttpRoutes);
  }
}

response 如下

{"data":"select * from test_data where name=?","ok":true,"msg":null,"code":1}

ref

  • https://www.ssssssss.org/magic-api/pages/base/script/
  • https://www.ssssssss.org/magic-api/pages/function/other/