Tomcat中WEB-INF/lib放MySQL驱动无效,放Tomcat/lib正常的原因咨询
问题原因分析
1. Tomcat类加载器的层级差异
Tomcat采用了变种的双亲委派类加载机制,不同目录下的Jar包由不同层级的类加载器负责加载:
WEB-INF/lib下的Jar包由WebAppClassLoader加载,属于当前Web应用专属的类加载器,仅当前应用可见,且层级低于Tomcat容器的类加载器。- Tomcat安装目录下
lib文件夹的Jar包由CommonClassLoader/SharedClassLoader加载,属于容器级类加载器,所有部署在Tomcat上的Web应用都能共享,且层级高于WebAppClassLoader。
2. JDBC驱动的注册与类加载可见性问题
JDK中的DriverManager类由最顶层的BootstrapClassLoader加载,它遵循类加载的可见性规则:父类加载器无法看到子类加载器加载的类。
- 当驱动包放在
WEB-INF/lib时,驱动类com.mysql.cj.jdbc.Driver由WebAppClassLoader加载,它的静态代码块会尝试把自己注册到DriverManager,但DriverManager(BootstrapClassLoader加载)看不到WebAppClassLoader加载的驱动类,后续调用DriverManager.getConnection()时自然找不到合适的驱动。 - 当驱动包放在Tomcat的
lib目录时,驱动类由容器级类加载器加载,这个类加载器是BootstrapClassLoader的子级,DriverManager能看到该层级加载的类,驱动注册后就能被正常识别。
3. 本地main方法测试正常的原因
本地运行main方法时,所有类(包括JDBC驱动)都是由**系统类加载器(AppClassLoader)**加载的,DriverManager和驱动类处于同一个类加载层级,不存在跨层级的可见性问题,所以能正常找到驱动并建立连接。
内容的提问来源于stack exchange,提问作者Koril
相关产品推荐
相关产品推荐

