Tomcat下Maven引入PostgreSQL JDBC无Class.forName无法加载及重复执行问题
问题1:PostgreSQL JDBC驱动无法自动注册的解决方案
导致该问题的核心原因是Tomcat类加载机制和JDBC4 SPI自动注册的逻辑冲突:JDBC的DriverManager由JDK根类加载器加载,SPI自动扫描驱动的动作在JVM启动阶段就会完成,此时Web应用自定义类加载器还未加载项目内的JDBC驱动,因此无法识别到PostgreSQL驱动。
可通过以下方案解决,无需手动调用Class.forName加载驱动:
- 清理重复依赖:你同时在Tomcat全局
lib目录和Maven项目中引入了PostgreSQL驱动,会引发类加载冲突。选择保留其中一处即可:
若保留Tomcat全局lib的驱动,需在pom.xml中将postgresql依赖的scope设置为provided,避免Maven重复将驱动打包进WEB-INF/lib目录
若保留项目内的驱动,删除Tomcat全局lib下的postgresql jar包,同时在Web应用的META-INF/context.xml的<Context>标签中添加配置:<Loader delegate="true"/>,开启Web应用SPI资源的优先扫描 - 更推荐的生产级方案:使用Tomcat JNDI数据源配置,在
context.xml中添加数据源配置,直接通过JNDI获取连接,完全规避驱动注册问题:
<Resource name="jdbc/postgres" auth="Container" type="javax.sql.DataSource" driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost/customer_tracker" username="hbstudent" password="hbstudent" maxTotal="20" maxIdle="10" maxWaitMillis="-1"/>
Java代码中获取连接的逻辑改为:
Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); DataSource ds = (DataSource) envCtx.lookup("jdbc/postgres"); Connection conn = ds.getConnection();
问题2:代码多次循环执行的原因
根据日志可以定位到几个常见触发原因:
- 浏览器自动重试:第一次请求抛出异常时,你没有给前端返回正常的响应头和内容,触发现代浏览器的自动重试机制,因此会重复发送GET请求
- 开发工具热部署/自动刷新:如果开启了IDEA热部署、LiveReload等自动刷新插件,代码修改后会自动触发页面刷新,生成新的请求
- 过滤器/拦截器重复调用:检查项目中配置的过滤器是否存在重复调用
chain.doFilter、请求转发逻辑,导致doGet方法被多次触发 - 注意你第一次报错的JDBC URL是
jdbc:postgresql://localhost/hb_student_tracker,和代码中写的customer_tracker不一致,说明第一次请求是旧代码运行结果,后续是代码更新生效后的重试请求,属于开发阶段的正常现象
内容的提问来源于stack exchange,提问作者iducam
相关产品推荐
相关产品推荐

