渣渣兔 发表于 2024-8-16 00:41:25

字符串值提取工具-04-java 调用 java? Janino 编译工具

值提取系列

值提取系列

字符串值提取工具-01-概览
字符串值提取工具-02-java 调用 js
字符串值提取工具-03-java 调用 groovy
字符串值提取工具-04-java 调用 java? Janino 编译工具
字符串值提取工具-05-java 调用 shell
字符串值提取工具-06-java 调用 python
字符串值提取工具-07-java 调用 go
代码地址

value-extraction 值提取核心
场景

我们希望通过 java 执行 java,怎样实现呢?
入门例子

代码

package org.example;

import javax.tools.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;

public class DynamicJavaExecutor {

    public static void main(String[] args) {
      // Java 代码字符串
      String javaCode =
                "public class HelloWorld { " +
                        "    public static void main(String[] args) { " +
                        "      System.out.println(\"Hello, World!\"); " +
                        "    } " +
                        "} ";

      // 编译 Java 代码
      boolean success = compileJavaCode("HelloWorld", javaCode);
      if (success) {
            try {
                // 使用 URLClassLoader 加载编译后的类
                File file = new File("./"); // 获取当前目录
                URL url = file.toURI().toURL(); // 转换为 URL
                URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
                Class<?> clazz = classLoader.loadClass("HelloWorld");

                // 调用类的 main 方法
                Method mainMethod = clazz.getMethod("main", String[].class);
                String[] params = null; // 传递给 main 方法的参数
                mainMethod.invoke(null, (Object) params);
            } catch (Exception e) {
                e.printStackTrace();
            }
      } else {
            System.out.println("Compilation failed.");
      }
    }

    public static boolean compileJavaCode(String className, String javaCode) {
      // 创建自定义的 JavaFileObject
      JavaFileObject fileObject = new InMemoryJavaFileObject(className, javaCode);

      // 获取系统 Java 编译器
      JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
      StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

      // 设置输出目录
      Iterable<String> options = Arrays.asList("-d", "./");

      // 编译 Java 代码
      JavaCompiler.CompilationTask task = compiler.getTask(
                null,
                fileManager,
                null,
                options,
                null,
                Arrays.asList(fileObject)
      );

      // 进行编译
      return task.call();
    }

    // 内部类,用于在内存中表示 Java 源文件
    static class InMemoryJavaFileObject extends SimpleJavaFileObject {
      private final String code;

      protected InMemoryJavaFileObject(String name, String code) {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
      }

      @Override
      public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return code;
      }
    }
}测试效果:
Hello, World!Janino 例子

maven 引入

<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>3.1.9</version>
</dependency>代码

package org.example;

import org.codehaus.janino.SimpleCompiler;

public class JaninoExample {

    public static void main(String[] args) throws Exception {
      // Java 代码字符串
      String javaCode =
                "public class HelloWorld { " +
                        "    public void run() { " +
                        "      System.out.println(\"Hello, World!\"); " +
                        "    } " +
                        "} ";

      // 创建编译器实例
      SimpleCompiler compiler = new SimpleCompiler();

      // 编译 Java 代码
      compiler.cook(javaCode);

      // 获取编译后的类
      Class<?> clazz = compiler.getClassLoader().loadClass("HelloWorld");

      // 创建类的实例
      Object instance = clazz.getDeclaredConstructor().newInstance();

      // 调用 run 方法
      clazz.getMethod("run").invoke(instance);
    }

}直接执行该方法

package com.github.houbb.value.extraction.test;

import org.codehaus.janino.ScriptEvaluator;

public class JavaDemoTest {

    public static void main(String[] args) throws Exception {
      // Java 脚本字符串
      String script =
                "System.out.println(\"Hello, World!\");";

      // 创建脚本求值器实例
      ScriptEvaluator scriptEvaluator = new ScriptEvaluator();

      // 编译并执行脚本
      scriptEvaluator.cook(script);
      scriptEvaluator.evaluate(null);
    }

}传入参数,直接执行

package com.github.houbb.value.extraction.test;

import org.codehaus.janino.ScriptEvaluator;

import java.util.HashMap;
import java.util.Map;

public class JaninoExample {

    public static void main(String[] args) throws Exception {
      // 创建一个包含参数的 Map
      Map<String, Object> bindings = new HashMap<>();
      bindings.put("a", 10);
      bindings.put("b", 20);

      // 定义要执行的脚本
      String script = "System.out.println(\"Result: \" + (a + b));";

      // 调用方法来执行脚本
      executeScriptWithBindings(script, bindings);
    }

    public static void executeScriptWithBindings(String script, Map<String, Object> bindings) throws Exception {
      // 提取 Map 中的键(参数名)和值(参数值)
      String[] parameterNames = bindings.keySet().toArray(new String);
      Class<?>[] parameterTypes = new Class<?>;

      // 假设所有参数的类型都是 Object,可以根据需要修改类型推断逻辑
      for (int i = 0; i < parameterNames.length; i++) {
            parameterTypes = bindings.get(parameterNames).getClass();
      }

      // 创建 ScriptEvaluator 实例
      ScriptEvaluator scriptEvaluator = new ScriptEvaluator();

      // 设置脚本的参数名称和类型
      scriptEvaluator.setParameters(parameterNames, parameterTypes);

      // 编译脚本
      scriptEvaluator.cook(script);

      // 提取 Map 中的值作为参数
      Object[] parameterValues = bindings.values().toArray();

      // 执行脚本
      scriptEvaluator.evaluate(parameterValues);
    }
}但是感觉这个很麻烦,而且有问题
另一种执行的方式

package com.github.houbb.value.extraction.test.javas;

import org.codehaus.commons.compiler.CompileException;
import org.codehaus.janino.ScriptEvaluator;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class JaninoScriptMapExample {

    public static void main(String[] args) throws CompileException, InvocationTargetException {
      // 示例脚本,使用 Map 参数
      String script =
                "return map.get(\"greeting\") + \", \" + map.get(\"name\") + \"!\";";

      // 创建 ScriptEvaluator 实例,指定返回类型、参数名和参数类型
      ScriptEvaluator se = new ScriptEvaluator(
                script,                      // 脚本代码
                Object.class,                // 返回值类型
                new String[]{"map"},         // 参数名列表
                new Class<?>[]{Map.class}    // 参数类型列表
      );

      // 准备传入的 Map 参数
      Map<String, Object> params = new HashMap<>();
      params.put("greeting", "Hello");
      params.put("name", "Janino");

      // 执行脚本,传入 Map 参数
      Object result = se.evaluate(new Object[]{params});

      // 输出结果
      System.out.println(result);
    }

}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 字符串值提取工具-04-java 调用 java? Janino 编译工具