【问题标题】:How compile Groovy source but not from filesystem如何编译 Groovy 源代码而不是从文件系统编译
【发布时间】:2015-11-09 02:55:06
【问题描述】:

我使用 GroovyClassLoader.parseClass(src) “即时”编译单个 groovy 源模块,一切正常。

但问题是当这个源模块导入其他类时,这些还没有编译。当我开始编译一个源但需要其他源并在源路径上准备好时,传统编译也会被编译。

如何使用带有目标的 GroovyClassLoader 来编译所有其他必需的源而不是来自 FILESYSYSTEM。 我的来源例如在数据库中,通过 URI 远程 http 等。

【问题讨论】:

  • public void setResourceLoader(GroovyResourceLoader resLoader) 和类 GroovyResourceLoader 对我来说很有趣吗?这么好的环境必须有从虚拟文件系统读取源的选项,我认为......
  • 我做同样/类似的事情。 setResourceLoader 是你的答案。
  • @lscoughlin 我已经在很多方面检查了 GroovyResourceLoader,概念上一切正常,事件被触发,导入是已知的等等,我可以在实现的 GroovyResourceLoader 中读取源代码片段但不能返回引用 URL。 GroovyClassLoader 在很多地方都使用了 URL,但在哲学 java URLLoader 中,项目路径的内部。另一个问题 GroovyClassLoader 有许多难以“替换”(覆盖)的私有元素。你成功实现你的想法了吗?
  • 是的。我在下面发布了我的解决方案。如果您有任何问题,请告诉我效果如何。

标签: groovy groovyclassloader


【解决方案1】:

关键是进行自定义 URL 处理——您必须实现 URLStreamHandlerURLConnection

如果你用谷歌搜索,有一些关于如何实现流处理程序和连接类的好文档——但对于你正在做的事情,你真的只需要虚拟实现。

这里有一些源代码可以引导您——它演示了如何将各个部分连接起来。如果你提供了一些 lookupScriptCodeWithJDBCorWhatever 的实现,你就可以开始了。

import groovy.lang.GroovyResourceLoader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

public class CustomGroovyResourceLoader implements GroovyResourceLoader {

    private final GroovyResourceLoader parentLoader;

    public CustomGroovyResourceLoader(GroovyResourceLoader parentLoader) {
        this.parentLoader = parentLoader;
    }

    @Override
    public URL loadGroovySource(String filename) throws MalformedURLException {
        URL resourceURL = null;

        if (parentLoader != null) {
            resourceURL = parentLoader.loadGroovySource(filename);
        }

        if (resourceURL == null) {
            resourceURL = createURL(filename);
        }

        return resourceURL;
    }

    public URL createURL(String resourceName) throws MalformedURLException {

        String scriptSourceCode = lookupScriptCodeWithJDBCorWhatever(resourceName);

        return new URL(null, "groovy:///" + resourceName,
                new GroovyResourceStreamHandler(scriptSourceCode));

    }

    private String lookupScriptCodeWithJDBCorWhatever(String resourceName) {

        //TODO: blah blah blah
        return null;
    }

    class GroovyResourceConnection extends URLConnection {

        private final String urlData;

        protected GroovyResourceConnection(URL url, String logic) {
            super(url);
            this.urlData = logic;
        }

        @Override
        public void connect() throws IOException {}

        @Override
        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(urlData.getBytes());
        }
    }

    class GroovyResourceStreamHandler extends URLStreamHandler {

        private final String scriptSource;

        public GroovyResourceStreamHandler(String scriptSource) {
            this.scriptSource = scriptSource;
        }

        @Override
        protected URLConnection openConnection(URL u) throws IOException {
            GroovyResourceConnection connection = new GroovyResourceConnection(u, scriptSource);
            return connection;

        }
    }

}

然后你用一些看起来像这样的代码安装这个东西:

GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
groovyClassLoader.setResourceLoader( new CustomGroovyResourceLoader( groovyClassLoader.getResourceLoader() ) );

【讨论】:

  • 非常感谢。我接近解决方案,以前我在有效注册全局 url-handler 时遇到问题(在许多线程/许多加载器服务器环境中可能有一些困难)。您的构造函数new URL(null, "groovy:///" + resourceName, new GroovyResourceStreamHandler(scriptSourceCode)); 需要一块拼图。据我了解,创建一次性 url 处理程序(带 url)
  • 没问题,我很高兴,我很高兴它为你解决了。是的,自定义流处理程序和关联对象附加到在该方法中构造的 URL,并且只存在于该方法中。
  • 补充。接口GroovyResourceLoader 没有准确记录loadGroovySource 如何以否定变体返回(找不到源 - 空或异常)。 Google 叔叔的几个样本返回 null;
  • 它没有记录在 API 文档中,但是快速浏览一下 GroovyClassLoader 的源代码会发现您为“找不到源”返回 null。
  • 完美答案,为我节省了大量时间。顺便说一句,URLConnection.getContent() 可以省略
猜你喜欢
  • 1970-01-01
  • 2015-01-28
  • 2022-07-05
  • 2018-09-08
  • 2018-02-26
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多