Java 如何在运行时加载Jasper定制器类?
我需要用图表呈现Jasper报表,并需要为它们提供单独的ChartCustomizer类。我的应用程序以Java web应用程序的形式运行 当前状态是,模板(.jasper文件)与它们所需的资源打包在一个单独的jar文件中。这些jar文件本身作为BLOB存储在数据库中。我用自己的FileResolver加载它们,并将其作为参数提供给Jasper引擎 到目前为止,这对我来说非常有用,只是我不能加载我的定制器类。我尝试将它们放在另一个jar文件中,用自己的类加载器加载它们,并将其提供给Jasper引擎:Java 如何在运行时加载Jasper定制器类?,java,templates,jasper-reports,classloader,Java,Templates,Jasper Reports,Classloader,我需要用图表呈现Jasper报表,并需要为它们提供单独的ChartCustomizer类。我的应用程序以Java web应用程序的形式运行 当前状态是,模板(.jasper文件)与它们所需的资源打包在一个单独的jar文件中。这些jar文件本身作为BLOB存储在数据库中。我用自己的FileResolver加载它们,并将其作为参数提供给Jasper引擎 到目前为止,这对我来说非常有用,只是我不能加载我的定制器类。我尝试将它们放在另一个jar文件中,用自己的类加载器加载它们,并将其提供给Jasper引
URL customizersUrl = classLoader.findResource("customizers.jar");
if (customizersUrl != null) {
URI jarUri = customizersUrl.toURI();
JarFile jarFile = new JarFile(new File(jarUri));
Enumeration e = jarFile.entries();
URL[] jarContentUrls = {new URL("jar:file:" + jarUri.getPath() + "!/")};
customizerClassLoader = URLClassLoader.newInstance(jarContentUrls);
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
if (je.isDirectory() || !je.getName().endsWith(".class")) {
continue;
}
// -6 because of .class
String className = je.getName().substring(0, je.getName().length() - 6);
className = className.replace('/', '.');
Class c = customizerClassLoader.loadClass(className);
}
}
parameters.put(JRParameter.REPORT_CLASS_LOADER, customizerClassLoader);
但是我仍然得到一个java.lang.ClassNotFoundException,尽管我可以在调试器中看到,从jar加载类是有效的
感谢您的帮助 好的,我发现我需要将类加载器放入当前线程的上下文中。我现在还使用匿名类加载器,以便只加载请求的类(还改进了调试)
// check if customizer classes are present and load them
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
final URL customizersUrl = classLoader.findResource("customizers.jar");
if (customizersUrl != null) {
ClassLoader cl = new ClassLoader() {
@Override
public Class loadClass(String className) throws ClassNotFoundException {
try {
return contextClassLoader.loadClass(className);
} catch (ClassNotFoundException ex) {
if (customizersUrl != null) {
try {
URI jarUri = customizersUrl.toURI();
URL[] jarContentUrls = {new URL("jar:file:" + jarUri.getPath() + "!/")};
URLClassLoader customizerInnerClassLoader = URLClassLoader.newInstance(jarContentUrls);
return customizerInnerClassLoader.loadClass(className);
} catch (URISyntaxException ex1) {
logger.debug("Exception during customizer class loading", ex1);
} catch (IOException ex1) {
logger.debug("Exception during customizer class loading", ex1);
} catch (ClassNotFoundException ex1) {
throw new ClassNotFoundException("Exception during customizer class loading", ex1);
}
}
}
return null;
}
};
// squeeze our own class loader in
Thread.currentThread().setContextClassLoader(cl);
}
byte[] result = generate(jasperReport, parameters);
// changing the class loader back to its origin... just to be safe
Thread.currentThread().setContextClassLoader(contextClassLoader);