6

我有一个 groovy 脚本 createWidget.groovy:

 import com.example.widget

 Widget w = new Widget()

当我像这样运行它时,这个脚本运行得很好:

$ groovy -cp /path/to/widget.jar createWidget.groovy

但是,我想在脚本中硬编码类路径,这样用户就不需要知道它在哪里,所以我修改了 createWidget.groovy 如下(这是在 groovy 中修改类路径的方法之一):

this.getClass().classLoader.rootLoader.addURL(new File("/path/to/widget.jar").toURL())

import com.example.widget

Widget w = new Widget()

但这总是失败并在导入时出现运行时错误:unable to resolve class com.example.widget.

这看起来确实不正统,我认为您不能在导入之前弄乱 rootLoader 还是其他什么?

4

4 回答 4

10
// Use the groovy script's classLoader to add the jar file at runtime.
this.class.classLoader.rootLoader.addURL(new URL("/path/to/widget.jar"));

// Note: if widget.jar file is located in your local machine, use following:
// def localFile = new File("/path/tolocal/widget.jar");
// this.class.classLoader.rootLoader.addURL(localFile.toURI().toURL());

// Then, use Class.forName to load the class.
def cls = Class.forName("com.example.widget").newInstance();
于 2014-06-23T22:21:21.810 回答
0

如果我理解这个问题,那么您要求的是一个可以交付给用户的独立单元。

这可以在 JVM 上使用“jar”的基础知识。

例如,这个项目玩一个名为 War-O 的简单游戏。用户可以使用以下命令运行它:

java -jar warO.jar [args]

该技术包括:(a) 将 Groovy 编译为类文件和 (b) 在 jar 中包含所有必要的 jar(包括 groovy-all)。此外,jar 必须具有清单中指定的“主要”入口点(这将是脚本的修改版本)。

War-O 项目使用 Gradle(请参阅此处的构建文件),但即使使用 Ant、Maven 等,原则也适用。以 Gradle 为例:

jar.archiveName 'warO.jar'
jar.manifest {
    attributes 'Main-Class' : 'net.codetojoy.waro.Main'
    attributes 'Class-Path' : 'jars/groovy-all-1.6.4.jar jars/guava-collections-r03.jar jars/guava-base-r03.jar'
}
于 2013-04-26T06:08:47.930 回答
0

另一种方法可以是只写下 java 代码以从 jar 文件加载类,并按照常规修改该代码。

import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Method;
public class JarFileLoader 
{
    public static void main (def args)
    {
        try
        {
            URLClassLoader cl = new URLClassLoader (new URL("jar:file:///path/to/widget.jar!/"));

            System.out.println ("Attempting...");

            Class beanClass = cl.loadClass ("com.example.widget.WidgetClass");
            Object dog = beanClass.newInstance();

            Method method = beanClass.getDeclaredMethod ("setBean", String.class);
            method.invoke (dog, "Who let the dog out");

            method = beanClass.getDeclaredMethod("getBean", null);            
            Object retObj = method.invoke (dog, null);

            String retVal = (String)retObj;

            System.out.println(retVal);
            System.out.println("Success!");
        }
        catch (Exception ex)
        {
            System.out.println ("Failed.");
            ex.printStackTrace ();
        }
    }
}
于 2016-08-23T10:40:11.010 回答
-1

Groovy 是一种编译语言,类名在编译时必须是可解析的。因此,在运行时添加 Jar 是不够的。

(import 语句也是错误的,你必须追加.*or .Widget。但这并不能解决更深层次的问题。)

于 2013-04-26T00:14:37.810 回答