【发布时间】:2011-08-28 06:41:18
【问题描述】:
我决定在我的 glassfish Web 应用程序中实现动态类加载,作为一种尝试的方式,并支持可以在运行时由 Web 应用程序加载和执行的小插件。
我添加了以下类:
public class PluginManager {
private static final String dropBoxDir = "file:///path/to/dropbox/";
private static final URLClassLoader dropBoxClassLoader;
static {
try {
URL dropBoxURL = new URL(dropBoxDir);
dropBoxClassLoader = URLClassLoader.newInstance(new URL[]{dropBoxURL});
}
catch (MalformedURLException mue) {
throw new RuntimeException("MalformedURLException thrown during PluginManager initialization - the hardcoded URL " + dropBoxDir + " must be invalid.", mue);
}
}
//this method is called by a web service
public static void runPluginFromDropBox(String fullClassName) {
try {
//load the plugin class
Class<?> pluginClass = dropBoxClassLoader.loadClass(fullClassName);
//instantiate it
Runnable plugin = (Runnable)pluginClass.newInstance();
//call its run() method
plugin.run();
}
catch (ClassNotFoundException cnfe) {
throw new RuntimeException("The class file for " + fullClassName + " could not be located at the designated directory (" + dropBoxDir + "). Check that the specified class name is correct, and that its file is in the right location.", cnfe);
}
catch (InstantiationException ie) {
throw new RuntimeException("InstantiationException thrown when attempting to instantiate the plugin class " + fullClassName + " - make sure it is an instantiable class with a no-arg constructor.", ie);
}
catch (IllegalAccessException iae) {
throw new RuntimeException("IllegalAccessException thrown when attempting to instantiate the plugin class " + fullClassName + " - make sure the class and its no-arg constructor have public access.", iae);
}
catch (ClassCastException cce) {
throw new RuntimeException("Plugin instance could not be cast to Runnable - plugin classes must implement this interface.", cce);
}
}
}
然后在一个单独的项目中,我创建了一个测试插件:
public class TestPlugin implements Runnable {
@Override
public void run() {
System.out.println("plugin code executed");
}
}
我部署了 Web 应用程序,然后将 TestPlugin 编译为 .class 文件并将其放入指定的文件夹中。我调用了一个 Web 服务,它使用类名点击 runPluginFromDropBox() 并获得了预期的输出。
这一切都作为概念证明,但我的插件实际上是无用的,除非它可以知道我的 Web 应用程序的类。我从那以后读到.war 仅用作独立应用程序,而不是用于其他库的类路径,这对于这个小项目来说并不是一个好兆头。
我看了这个讨论:Extending Java Web Applications with plugins,感觉我正无缘无故地陷入设计挑战的沼泽,应该转过身来。然而,那篇文章有点老了,而且是 Tomcat 特有的,所以我只是想问问是否有任何直接的方法可以让我在没有一些复杂的第三方框架的情况下解决这个问题。
【问题讨论】:
标签: java plugins glassfish classloader war