(tomcat中级)使用Tomcat的WebappClassLoader加载指定目录的jar文件
(tomcat中级)应用Tomcat的WebappClassLoader加载指定目录的jar文件
要点
- 用WebappClassLoader::addRepository就可以实现。不用扩展WebappClassLoader类。
- 当ServletContextListener::contextInitialized时,调用addRepository。
- 在各个context-param中指定jar所在路径。
ServletContextListener
package cn.net.tianyu.classloader.servlet; import java.io.File; import java.io.FilenameFilter; import java.net.MalformedURLException; import java.util.StringTokenizer; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.catalina.loader.WebappClassLoader; public class ClassLoadListener implements ServletContextListener { private static final String CONTEXT_PARAM_NAME_EXTLIBPATH = "net.tianyu.servlet.extlibs"; @Override public void contextInitialized(ServletContextEvent event) { ServletContext context = event.getServletContext(); addJar(context); } @Override public void contextDestroyed(ServletContextEvent event) { } synchronized private void addJar(ServletContext context) { String extlibs = context.getInitParameter(CONTEXT_PARAM_NAME_EXTLIBPATH); if (extlibs == null || extlibs.length() == 0) return; WebappClassLoader loader = (WebappClassLoader) getClass().getClassLoader(); StringTokenizer st = new StringTokenizer(extlibs, ","); while (st.hasMoreTokens()) { String jarPath = st.nextToken(); String jarRealPath = context.getRealPath(jarPath); File jarDir = new File(jarRealPath); if (!jarDir.isDirectory()) continue; File[] jarFiles = jarDir.listFiles(new JarFileNameFilter()); for (File jarFile : jarFiles) { try { loader.addRepository(jarFile.toURI().toURL().toString()); } catch (MalformedURLException e) { } } } } class JarFileNameFilter implements FilenameFilter { public boolean accept(File dir, String name) { return name.toLowerCase().endsWith(".jar"); } } }
web.xml
<?xml version="1.0" encoding="Shift_JIS"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <context-param> <param-name>net.tianyu.servlet.extlibs</param-name> <param-value>/../../extlib,/../../otherlib</param-value> </context-param> <listener> <listener-class>cn.net.tianyu.classloader.servlet.ClassLoadListener</listener-class> </listener> <servlet> <servlet-name>sample</servlet-name> <servlet-class>cn.net.tianyu.classloader.servlet.SampleServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sample</servlet-name> <url-pattern>/sample</url-pattern> </servlet-mapping> </web-app>
1 楼
stevendu
2009-09-09
执行到 WebappClassLoader loader = (WebappClassLoader) getClass().getClassLoader(); 时报错!
严重: Exception sending context initialized event to listener instance of class com.zoove.dcp.jars.JarLoaderListener
java.lang.ClassCastException: org.apache.catalina.loader.WebappClassLoader cannot be cast to org.apache.catalina.loader.WebappClassLoader
at com.zoove.dcp.jars.JarLoaderListener.addJar(JarLoaderListener.java:35)
at com.zoove.dcp.jars.JarLoaderListener.contextInitialized(JarLoaderListener.java:25)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4350)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:924)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:887)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
2009-9-9 23:41:47 org.apache.catalina.core.StandardContext start
严重: Error listenerStart
2009-9-9 23:41:47 org.apache.catalina.core.StandardContext start
严重: Context [/dcp] startup failed due to previous errors
严重: Exception sending context initialized event to listener instance of class com.zoove.dcp.jars.JarLoaderListener
java.lang.ClassCastException: org.apache.catalina.loader.WebappClassLoader cannot be cast to org.apache.catalina.loader.WebappClassLoader
at com.zoove.dcp.jars.JarLoaderListener.addJar(JarLoaderListener.java:35)
at com.zoove.dcp.jars.JarLoaderListener.contextInitialized(JarLoaderListener.java:25)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4350)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:924)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:887)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1147)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
2009-9-9 23:41:47 org.apache.catalina.core.StandardContext start
严重: Error listenerStart
2009-9-9 23:41:47 org.apache.catalina.core.StandardContext start
严重: Context [/dcp] startup failed due to previous errors
2 楼
stevendu
2009-09-09
难道是我的jar包用错了? 我用的catalina.jar啊。
3 楼
stevendu
2009-09-10
问题找到了,我应该在部署后的lib中删除catalina.jar
4 楼
mahengyang
2011-09-16
为什么用tomcat启动web工程时需要将用到的jar包都放在WEB-INF/lib目录下呢?我在工程里的BuildPath里也设置了需要的jar包的路径,但是程序运行后还是会报出CLASSNOTFOUNDEXCEPTION,当我把所有的jar包都放到WEB-INF/lib下面后就好了。