我有一个groovy脚本createWidget.groovy:
import com.example.widget
Widget w = new Widget()
当我像这样运行它时,这个脚本运行得很好:
$ groovy -cp /path/to/widget.jar createWidget.groovy
但是,我想在脚本中硬编码类路径,以便用户不需要知道它在哪里,所以我修改了createWidget.groovy如下(这是在groovy中修改类路径的方法之一): / p>
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,还是别的什么?
答案 0 :(得分:9)
// 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();
答案 1 :(得分:0)
Groovy是一种编译语言,类名必须在编译时可解析。因此,在运行时添加Jar是不够的。
(导入声明也是错误的,您必须附加.*
或.Widget
。但这不会解决更深层次的问题。)
答案 2 :(得分:0)
如果我理解了这个问题,那么你就需要一个可以交付给用户的独立单元。
这可以使用JVM上的'jar'基础知识。
例如,this project扮演一个名为War-O的简单游戏。用户可以使用以下命令运行它:
java -jar warO.jar [args]
该技术包括:(a)将Groovy编译为类文件,以及(b)在jar中包含所有必需的jar(包括groovy-all)。此外,jar必须具有清单中指定的“主”入口点(这将是脚本的修改版本)。
War-O项目使用Gradle(参见build file here),但即使使用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'
}
答案 3 :(得分:0)
另一种方法可以是写下java代码从jar文件中加载类,并按照groovy修改该代码。
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 ();
}
}
}