问题描述
工作原理:我有一个实用程序,可以读取一堆常规脚本文件并执行它们。如果这些 groovy 脚本文件被放置在工作目录中的 jar 之外,那么它们会被拾取并按预期运行。
final class PluginBootStrapper {
private final GroovyScriptEngine scriptEngine = null
private final List<Plugin> allPlugins = null;
private final Logger logger = Logger.getLogger(PluginBootStrapper.class)
public PluginBootStrapper()
{
String pluginsDir = System.getProperty(ABCProperties.endorsed_plugins_dir)
scriptEngine = new GroovyScriptEngine(CommonUtils.getAllDirectories(
pluginsDir))
logger.info "Plugins Directory:"+System.getProperty(ABCProperties.endorsed_plugins_dir)
allPlugins = loadDescriptor().invokeMethod("getAllPlugins",null)
}
private Object loadDescriptor() {
Object pluginDescriptor = bootStrapScript(abcProperties.get(abcProperties.PLUGIN_DESCRIPTOR))
pluginDescriptor
}
Object bootStrapScript(String script) {
Object pluginScript = scriptEngine.loadScriptByName(script)
.newInstance()
pluginScript
}
public List<Plugin> getAllPlugins()
{
return allPlugins
}
}
问题:现在我需要将这些 groovy 脚本放在 jar 文件中,我尝试在 bootStrapScript
函数中更改以下语句
Object bootStrapScript(String script) {
String path = this.getClass().getClassLoader().getResource(script).toExternalForm()
logger.info "bootStrapScript script "+ path
Object pluginScript = scriptEngine.loadScriptByName(script)
.newInstance()
pluginScript
}
但它无法找到groovy脚本并抛出以下异常(jar内容的屏幕截图附在下面,甚至尝试将所有脚本文件放在plugins文件夹中)
Exception in thread "main" groovy.util.ResourceException: No resource for Plugins.groovy was found
at groovy.util.GroovyScriptEngine.getResourceConnection(GroovyScriptEngine.java:421)
at groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:558)
at groovy.util.GroovyScriptEngine$loadScriptByName.call(UnkNown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at com.jagra.abc.plugins.PluginBootStrapper.bootStrapScript(PluginBootStrapper.groovy:42)
at com.jagra.abc.plugins.PluginBootStrapper$bootStrapScript.callCurrent(UnkNown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
at com.jagra.abc.plugins.PluginBootStrapper.loadDescriptor(PluginBootStrapper.groovy:33)
at com.jagra.abc.plugins.PluginBootStrapper.<init>(PluginBootStrapper.groovy:28)
at com.jagra.abc.abc.run(abc.java:65)
at com.jagra.abc.abcMain.main(abcMain.java:15)
注意:这里是 pluginsDir
是 .\plugins
解决方法
据我所知,jar文件中没有资源的文件路径这样的东西,因为资源不是文件。
当“文件”在 jar 文件中时,您需要将其作为资源加载,而不是作为文件加载,例如 getResourceAsStream()。
加载文件和加载非文件资源的共同点是它们都可以作为流加载。
所以,我可以想到两个解决方案:
A:更改您的脚本加载器以支持文件和资源,以不同的方式加载。
或
B:将您的脚本加载器更改为始终读取流,并在加载器之外提供加载文件或资源的功能,并将生成的流提供给脚本加载器。