每当我在tomcat中部署Web应用程序时,WEB-INF / lib中的所有jar都将被加载到应用程序ClassLoader中。
我的其他几个地方都有一些罐子,比如WEB-INF / ChildApp1 / * .jar,WEB-INF / ChildApp2 / * .jar ..... 根据用户请求,我想将一些jar加载到当前的类加载器中。
注意:我不想创建任何子类加载器。
我真正的要求是,以编程方式将jar添加到当前的类加载器中。
答案 0 :(得分:3)
我曾经做过一次,但这有点像黑客。请参阅以下代码:
final URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
final Class<URLClassLoader> sysclass = URLClassLoader.class;
// TODO some kind of a hack. Need to invent better solution.
final Method method = sysclass.getDeclaredMethod("addURL", new Class[] { URL.class });
method.setAccessible(true);
for (final File jar : jars) {
method.invoke(sysloader, new URL[] { jar.toURI().toURL() });
}
您需要将ClassLoader.getSystemClassloader()更改为要使用的类加载器。您还必须检查这是否是URLClassloader的实例 我认为有更好的解决方案,但这对我有用
答案 1 :(得分:2)
您需要在context.xml
的{{3}}配置中实施自己的WebappClassLoaderBase
。
WebappClassLoaderBase
最简单的方法是将loader
扩展为下一个
package my.package;
public class MyWebappClassLoader extends WebappClassLoader {
public MyWebappClassLoader() {
}
public MyWebappClassLoader(final ClassLoader parent) {
super(parent);
}
@Override
public void start() throws LifecycleException {
String[] paths = {"/WEB-INF/ChildApp1/lib", "/WEB-INF/ChildApp2/lib"};
// Iterate over all the non standard locations
for (String path : paths) {
// Get all the resources in the current location
WebResource[] jars = resources.listResources(path);
for (WebResource jar : jars) {
// Check if the resource is a jar file
if (jar.getName().endsWith(".jar") && jar.isFile() && jar.canRead()) {
// Add the jar file to the list of URL defined in the parent class
addURL(jar.getURL());
}
}
}
// Call start on the parent class
super.start();
}
}
WebappClassLoaderBase
WebappClassLoader
提供的tomcat版本对应的tomcat jar构建您自己的WebappClassLoaderBase
。WebappClassLoaderBase
在WebappClassLoaderBase
context.xml
<Context>
...
<Loader loaderClass="my.package.MyWebappClassLoader" />
</Context>
完成后,现在您的webapps将能够从/WEB-INF/ChildApp1/lib
和/WEB-INF/ChildApp2/lib
加载jar文件。
如果你想做同样的事情但只有war
,你需要使用黑客来动态添加你的jar
文件。
以下是您可以继续操作的方法:
ServletContextListener
添加jar文件为了在初始化上下文时动态添加jar
文件,您需要创建一个ServletContextListener
,它将通过反复调用Common ClassLoader
,这是一个丑陋的黑客但它可以正常工作。请注意,它的工作原理是因为Tomcat中的Web应用程序的ClassLoader
是WebappClassLoader
,它实际上是URLClassLoader
的子类。
package my.package;
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(final ServletContextEvent sce) {
try {
// Get the method URLClassLoader#addURL(URL)
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
// Make it accessible as the method is protected
method.setAccessible(true);
String[] paths = {"/WEB-INF/ChildApp1/lib", "/WEB-INF/ChildApp2/lib"};
for (String path : paths) {
File parent = new File(sce.getServletContext().getRealPath(path));
File[] jars = parent.listFiles(
new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.endsWith(".jar");
}
}
);
if (jars == null)
continue;
for (File jar : jars) {
// Add the URL to the context CL which is a URLClassLoader
// in case of Tomcat
method.invoke(
sce.getServletContext().getClassLoader(),
jar.toURI().toURL()
);
}
}
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
@Override
public void contextDestroyed(final ServletContextEvent sce) {
}
}
ServletContextListener
在您的网络应用的web.xml
中,只需添加:
<listener>
<listener-class>my.package.MyServletContextListener</listener-class>
</listener>