我正在使用Java库,该库在lib
程序包中具有一些嵌套的JAR文件。
我有2个问题:
我知道我必须创建并使用自定义的ClassLoader,它可以解决这两个问题吗?这是获得此结果的推荐方法吗?
JAR文件是意大利政府提供的库,由于法规会定期更新,因此我无法对其进行修改。
我不知道装完罐子后要做什么。就我而言,对Servlet示例使用jar动态加载。
try{
final URLClassLoader loader = (URLClassLoader)ClassLoader.getSystemClassLoader();
final Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
new File(dir).listFiles(new FileFilter() {
@Override
public boolean accept(File jar) {
// load file if it is 'jar' type
if( jar.toString().toLowerCase().contains(".jar") ){
try {
method.invoke(loader, new Object[]{jar.toURI().toURL()});
XMLog.info_arr(logger, jar, " is loaded.");
JarInputStream jarFile = new JarInputStream(new FileInputStream(jar));
JarEntry jarEntry;
while (true) {
// load jar file
jarEntry = jarFile.getNextJarEntry();
if (jarEntry == null) {
break;
}
// load .class file in loaded jar file
if (jarEntry.getName().endsWith(".class")) {
Class loadedClass = Class.forName(jarEntry.getName().replaceAll("/", "\\.").replace(".class",""));
/*
* In my case, I load jar file for Servlet.
* If you want to use it for other case, then change below codes
*/
WebServlet annotaions = (WebServlet) loadedClass.getAnnotation(WebServlet.class);
// load annotation and mapping if it is Servlet
if (annotaions.urlPatterns().length > 0) {
ServletRegistration.Dynamic registration = servletContextEvent.getServletContext().addServlet(annotaions.urlPatterns().toString(), loadedClass);
registration.addMapping(annotaions.urlPatterns());
}
}
}
} catch (Exception e) {
System.err.println("Can't load classes in jar");
}
}
return false;
}
});
} catch(Exception e) {
throw new RuntimeException(e);
}
是,据我所知,标准的ClassLoader不支持嵌套JAR。
如果要从其他人那里获得这些JAR,最好的办法是与供应商联系,并要求他们提供标准兼容格式的产品。从您的回答中,我意识到这可能很难实现,但是我仍然会尝试与他们交谈,因为这是正确的做法。我很确定您所处位置的其他所有人都有同样的问题。根据行业标准,这种情况通常会提示您的供应商将Maven存储库用于其可交付成果。
如果与您的供应商交谈失败,您可以在收到JAR时重新打包它们。我建议为此编写一个自动化脚本,并确保它在每次交付时都运行。您可以将所有.class文件放入一个uber-JAR中,也可以将嵌套的JAR移到封闭的JAR之外。注意事项1:可以有多个同名课程,因此您需要确保选择正确的一个。注意事项2:如果JAR已签名,则您将丢失签名(除非您用自己的签名)。
选项3:您始终可以实现自己的ClassLoader,以从任何地方(甚至从厨房水槽)加载类。
此人正是这样做的:https://www.ibm.com/developerworks/library/j-onejar/index.html
您可以将他的解决方案用作“包装程序加载器”,它将替换您的主类。
就IntelliJ IDEA而言,我不认为它支持现成的功能。最好的办法是如上所述重新打包JAR并将其添加为单独的类路径条目,或者搜索是否有人编写了用于嵌套JAR支持的插件。