7

我们正在为 groovy 脚本寻找一种包含机制,以便为横切关注点留出空间。

在我的示例中,我们将 Web 服务端点作为 groovy 脚本并希望登录到我们的 Web 服务协议。为此,我们使用隐式对象(从我们的框架中获取)来创建日志记录语句。

但如果我们在每个 Web 服务端点中编写代码,这就是样板代码。

我们正在 php 中搜索 include() 之类的东西,其中包括其他 groovy 脚本,有什么想法可以做到这一点吗?

4

7 回答 7

10

Groovy 将其文件视为对象(将其视为自动包装)。它使 java 类路径中的所有 .groovy 文件都可以作为类使用。因此,如果您有 util.groovy 文件,其中包含以下内容:

def static AuxMethod() {
    return "Hello World"
}

要从另一个文件中调用它,您只需编写:

println util.AuxMethod()

就是这样。同样,只需确保您的 util.groovy 文件位于类路径中。

于 2010-12-02T14:55:59.013 回答
2

要从当前脚本调用脚本u.groovy,将原始参数传递给 u.groovy,运行

run(new File('u.groovy'), args)

显然,您还可以发送任何您想要的字符串参数:

run(new File('u.groovy'),
        ['one', new File('two.text').absolutePath] as String[])
于 2011-10-20T16:24:02.340 回答
1

查看评估(文件)函数:

 Object evaluate(File file) 

http://groovy.codehaus.org/api/groovy/lang/Script.html

于 2009-08-12T07:30:25.370 回答
1

既然您已经提到了“横切关注点”,我想说您需要拦截您的 Web 服务调用AOP样式(不是包含机制)。

Grails 与Spring 框架完全集成,因此这为利用 Spring AOP 特性提供了一个很好的选择。从 grails 官方指南中查看本章:http: //grails.org/doc/latest/guide/14.%20Grails%20and%20Spring.html并搜索单词 AOP。

也许有一种纯粹的 AOP 方式,但我会选择 grails 和 spring。

于 2009-08-12T17:39:33.423 回答
1

我针对我正在创建的领域特定语言对此进行了一些研究。有三种可能:

  1. 将您的类创建为继承父 groovy 类。将您的共享代码放在基类中。

  2. 使用 ScriptBaseClass 参见http://groovy.codehaus.org/Embedding+Groovy。这是一个将在其上创建所有脚本的类。

  3. 使用导入静态方法功能。请注意,您可以在 java 容器中执行此操作(请参阅http://mrhaki.blogspot.com/2011/06/groovy-goodness-add-imports.html)。

所有这些工作都很棒。我的首选是 ScriptBaseClass。如果公共代码是 Groovy,这效果最好(ScriptBaseClass必须是 groovy 类。它不能是 java 类。)

当然,对于所有这些项目,您仍然需要在 groovy 代码中实际调用公共方法。例如:

doCommonStuff();
.
. do the rest of it here
.

这不是太可怕,我不认为。当然与添加某种#include 预处理器语句大致相同。

最后,所有这些都假设您可以访问调用 Groovy 代码的 java 程序。如果不是这种情况,您仍然可以使用静态导入。这只是额外的一行代码。

import static com.mycompany.mycode.doCommonStuff
doCommonStuf()
.
. do the rest of it here
.
于 2012-01-22T16:40:52.623 回答
0

我发现这个邮件列表很有帮助。 http://groovy.329449.n5.nabble.com/Groovy-scripts-Reusing-declared-methods-in-other-scripts-How-Include-td5703723.html

于 2013-08-28T00:10:13.370 回答
0

我为我的脚本创建了一个预处理器。它搜索特定include模式,这是一个示例:

public final class IncludePreprocessor {

    @FunctionalInterface
    public interface IncludeLoader {

        InputStream load(String include) throws IOException;

    }

    private static final Pattern INCLUDE_PATTERN = Pattern.compile("include\\s+(.+)$");

    private final IncludeLoader includeLoader;

    public IncludePreprocessor(IncludeLoader includeLoader) {
        this.includeLoader = includeLoader;
    }

    public boolean preprocess(InputStream mainScript, Writer outputScript) throws IOException {
        boolean preprocessed = false;
        try (Scanner sc = new Scanner(mainScript)) {
            while (sc.hasNextLine()) {
                String line = sc.nextLine();

                Matcher m = INCLUDE_PATTERN.matcher(line);
                if (m.matches()) {
                    outputScript.append("//").append(line).append(System.lineSeparator());

                    String include = m.group(1);
                    try (InputStream in = includeLoader.load(include)) {
                        StringWriter sw = new StringWriter();
                        preprocess(in, sw);
                        outputScript.append(sw.toString()).append(System.lineSeparator());
                        preprocessed = true;
                    }
                    outputScript.append("//").append(line).append(" [EOF]").append(System.lineSeparator());
                } else {
                    outputScript.append(line).append(System.lineSeparator());
                }
            }
        }

        return preprocessed;
    }
}

以及如何使用它:

//common.groovy
def sum(a,b) {
   a + b
}

// main.groovy
include common.groovy
sum(1,2)


// Demo.java
public class Demo {
    public static void main(String[] args) {
        IncludePreprocessor ip = new IncludePreprocessor(include -> new FileInputStream("./" + include));
        
        StringWriter sw = new StringWriter();
        ip.preprocess(new FileInputStream("./main.groovy", sw));
        System.out.println(sw.toString());
    }
}
于 2020-07-29T19:39:32.843 回答