gpt4 book ai didi

java - 在Java中如何在执行时注入(inject)代码?

转载 作者:行者123 更新时间:2023-12-02 01:22:44 25 4
gpt4 key购买 nike

我正在开发一个 java spring 应用程序,我需要提供在不更改标准代码的情况下添加新代码的能力。

我的挑战:

  1. 将“自定义”代码存储在数据库中
  2. 在执行时将代码注入(inject)现有标准代码
  3. 隔离自定义代码,以便两个用户不会执行彼此的代码。

换句话说,我正在寻找的是在方法执行时,查看数据库是否用户有此方法的自定义代码,如果没有,则执行标准代码;如果是,则注入(inject)代码,执行修改后的方法,然后处理自定义代码。

我研究过 AspectJ 和 Javassist。我有一个使用 AspectJ 的流程,但只有当自定义代码位于它自己的 jar 中并在构建/运行时添加时,我才能让它工作。我没有花太多时间使用 Javassist,但从文档来看,我似乎处于同一条船上。

这是我想要做的一个极其简单的示例。

@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {

String results = "";

results = "foo";

//<-- insert custom code here (if exists) each time method is invoked

results += "bar";

return results;
}
}

最佳答案

关于 JSR-223 的 Java 脚本支持,这里有一些 introductory documentation为你。

默认情况下,Nashorn JavaScript 引擎包含在 JRE 中,但从 Java 11 开始,您会收到一条警告,表明它已被弃用,并将在将来被删除。这不是一个大问题,因为您仍然可以使用它,并且还有其他 JSR-223 兼容的脚本语言可用。

这个例子展示了如何使用

  • JavaScript,
  • Groovy 和
  • Lua

来自 Java 的脚本。请确保添加相应的

如果您想使用额外的两种语言而不仅仅是内置的 JS 引擎,请将库添加到您的类路径中。

每种语言的脚本都演示了相同的基础知识,即如何

  • 从脚本调用 Java 对象的方法 (File.getCanonicalPath()),
  • 如何将字符串转换为大写,
  • 如何重复一个字符串(在 JS 中,我们必须为此定义自己的原型(prototype)方法,因为 Nashorn 本身没有实现 repeat(n) 方法)。
package de.scrum_master.app;

import java.io.File;
import javax.script.*;

public class Application {
private static final ScriptEngineManager MANAGER = new ScriptEngineManager();

public static void main(String[] args) throws ScriptException {
listScriptingEngines();
System.out.println(runScript("JavaScript", "print(file.getCanonicalPath()); String.prototype.repeat = function(num) { return new Array(num + 1).join(this) }; (text.toUpperCase() + '_').repeat(2)"));
System.out.println(runScript("Groovy", "println file.canonicalPath; (text.toUpperCase() + '_') * 2"));
System.out.println(runScript("lua", "print(file:getCanonicalPath()); return string.rep(string.upper(text) .. '_', 2)"));
}

public static void listScriptingEngines() {
for (ScriptEngineFactory factory : MANAGER.getEngineFactories()) {
System.out.printf("Script Engine: %s (%s)%n", factory.getEngineName(), factory.getEngineVersion());
System.out.printf(" Language: %s (%s)%n", factory.getLanguageName(), factory.getLanguageVersion());
factory.getNames().stream().forEach(name -> System.out.printf(" Alias: %s%n", name));
}
}

public static String runScript(String language, String script) throws ScriptException {
ScriptEngine engine = MANAGER.getEngineByName(language);
// Expose Java objects as global variables to script engine
engine.put("file", new File("/my/" + language + "/test.txt"));
engine.put("text", language);
// Use script result for generating return value
return engine.eval(script) + "suffix";
}
}

如果您在类路径上使用 groovy-all 运行程序,输出应如下所示:

Script Engine: Groovy Scripting Engine (2.0)
Language: Groovy (2.4.13)
Alias: groovy
Alias: Groovy
Script Engine: Luaj (Luaj-jse 3.0.1)
Language: lua (5.2)
Alias: lua
Alias: luaj
Script Engine: Oracle Nashorn (1.8.0_211)
Language: ECMAScript (ECMA - 262 Edition 5.1)
Alias: nashorn
Alias: Nashorn
Alias: js
Alias: JS
Alias: JavaScript
Alias: javascript
Alias: ECMAScript
Alias: ecmascript
C:\my\JavaScript\test.txt
JAVASCRIPT_JAVASCRIPT_suffix
C:\my\Groovy\test.txt
GROOVY_GROOVY_suffix
C:\my\lua\test.txt
LUA_LUA_suffix

当然,在您自己的代码中,您应该用从代码片段数据库加载的特定于用户的内容替换内联 JS、Groovy 或 Lua 代码。您还应该考虑要向脚本引擎公开哪些变量并为用户记录它。

关于java - 在Java中如何在执行时注入(inject)代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57421207/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com