基于RESTEasy/Shiro/jOOQ的Java服务:Tomcat无法加载H2驱动
我之前在做类似技术栈的项目时,也踩过Tomcat全局数据源驱动加载失败的坑,结合你的场景,给你几个针对性的排查和修复步骤:
确认H2驱动包的放置位置与版本
Tomcat普通版(非EE)不会自带H2驱动,你必须把h2-xxx.jar放到$CATALINA_HOME/lib目录下(不是项目的WEB-INF/lib),因为全局数据源需要Tomcat容器级别的驱动支持。另外建议选H2 1.4.x系列版本,和Tomcat 8.5兼容性更好,避免用太新的版本出现适配问题。检查context.xml的数据源配置正确性
别照搬MySQL的配置直接改,H2的配置有自己的格式,给你一个标准的内嵌H2数据源配置示例:<Resource name="jdbc/MyH2DB" auth="Container" type="javax.sql.DataSource" driverClassName="org.h2.Driver" url="jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE" username="sa" password="" maxTotal="100" maxIdle="30" maxWaitMillis="10000"/>重点注意:
driverClassName必须是org.h2.Driver,别写成MySQL的驱动类;URL要匹配你用的H2模式(内嵌、内存、TCP远程),比如内存模式是jdbc:h2:mem:test,要根据自己的需求调整。验证web.xml的资源引用配置
确保项目的web.xml里添加了对应的资源引用,而且名称要和context.xml里的name完全一致:<resource-ref> <description>H2 Database Connection Pool</description> <res-ref-name>jdbc/MyH2DB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>确认jOOQ的数据源获取逻辑
因为你用jOOQ作为ORM,要确保是通过Tomcat的JNDI来获取数据源,而不是自己手动加载驱动。正确的获取方式应该是这样的:try { InitialContext ctx = new InitialContext(); DataSource dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/MyH2DB"); DSLContext dslContext = DSL.using(dataSource, SQLDialect.H2); // 后续jOOQ操作 } catch (NamingException e) { e.printStackTrace(); }这里一定要注意JNDI路径的前缀
java:comp/env/,Tomcat下必须加这个前缀才能正确找到全局数据源。查看Tomcat日志定位具体错误
接口报错只是表象,真正的驱动加载问题会在Tomcat的日志里体现。去$CATALINA_HOME/logs目录下看localhost.log或者catalina.out,如果是ClassNotFoundException: org.h2.Driver,那就是驱动包没放对位置;如果是SQL异常,大概率是URL或者用户名密码配置错误。
内容的提问来源于stack exchange,提问作者Rico

