在过去的几年里,我没有用这种传统的方式把战争部署到一只猫身上。
在这些天里,我尝试更新到Spring 6/Jakarta 9/Java 17,并创建了一个演示Spring应用程序的简单示例,当通过cargo maven插件或手动部署到Tomcat 10时,在应用程序启动阶段初始化hibernate时,我获得了著名的no合适的驱动程序。
但它在单元测试中有效。
我还尝试部署到外部Tomcat服务器上,首先将postgres jar复制到tomcat/lib文件夹,然后将war包复制到tomcat/webapp文件夹,然后手动启动它,但是得到了相同的错误。
我的示例项目:https://github.com/hantsy/spring6-sandbox/tree/master/jpa,基于以下技术堆栈:
要再现这些问题,请通过docker compose up postgres启动Postgres,并在项目文件夹中运行mvn clean package cargo:run -Ptomcat以部署到cargo托管tomcat服务器。
PS:我还配置了Jetty和WildFly,它们都工作得很好。
更新:这个问题有点奇怪,因为将Postgres驱动程序打包到war中可以很好地处理Spring5/Tomcat9 9。但是它在这个升级到Spring6/Tomcat10 10的示例中失败了。要使其工作,我必须将从war包中排除pg驱动程序,并将其复制到普通的tomcat/lib文件夹中,有关更多细节,请参见集成测试。有关Jdbc驱动程序加载的更多信息,请参见@PiotrP.Karwasz的答案。
顺便说一下,Tomcat是Java开发人员的首选web服务器,其中一个原因是大多数流行的Jdbc驱动程序在将其打包为was时工作良好,而传统的应用服务器(WildFly、Glassfish等)在过去几年中不支持它(您必须通过应用服务器命令行工具或管理控制台将其安装到应用服务器)。但是由于Java 7,它允许开发人员定义应用程序作用域的DataSource(通过@DataSourceDefinition),并将Jdbc驱动程序直接打包到应用程序war包中,当应用程序被部署时,它将自动注册Jdbc驱动程序。不知道为什么最新的Tomcat会增加开发复杂性,并使用遗留应用程序服务器方法。
发布于 2022-01-02 17:41:11
简短回答:在DataSourceConfig类中,您不调用DriverManagerDataSource#setDriverClassName,因此DriverManager不知道在哪里为jdbc:postgresql: URI找到合适的驱动程序。
长答案:等等,我真的需要指定驱动程序的类名吗,难道JDBC驱动程序没有自动检测到吗?是的,因为Java6和JDBC4,JDBC驱动程序是通过ServiceLoader机制自动检测的。
但是,在第一次调用期间,只发生一次DriverManager.getDrivers()。Tomcat确保这发生在服务器的类路径(cf )中。JreMemoryLeakPrevention),因此只有全局安装的驱动程序被注册(系统类加载器不保存对应用程序类加载器的引用)。
因此,不必指定驱动程序的类名,您可以:
$CATALINA_BASE/lib),然后从应用程序中删除,DriverManager使用的自动发现机制来注册与应用程序一起分发的所有驱动程序:私有静态registerJdbcDrivers(ServletContext上下文){ ServiceLoader serviceLoader = ServiceLoader.load(Driver.class,context.getClassLoader());final Iterator iter = serviceLoader.iterator();而(iter.hasNext()) { //只是为了加载类和注册驱动程序iter.next()的副作用;}https://stackoverflow.com/questions/70554119
复制相似问题