在過去的幾年里,我沒有使用這種傳統方式將戰爭部署到 tomcat。
這幾天,我嘗試將自己更新到 Spring 6/Jakarta EE 9/Java 17 并創建了一個簡單的示例來演示 Spring WebMvc war 應用程式,當通過cargo maven 插件或手動部署到 Tomcat 10 時,我得到了著名的no hibernate 初始化時,應用程式啟動階段的合適驅動程式。
但它在單元測驗中有效。
我也試過部署到外部Tomcat服務器,先復制一個postgres jar到tomcat/lib檔案夾下,然后把war包復制到tomcat/webapps檔案夾下,手動啟動,還是一樣的錯誤。
我的示例專案:https : //github.com/hantsy/spring6-sandbox/tree/master/jpa,基于以下技術堆疊:
- 雅加達 EE 9/Java 17
- 彈簧 6.0.0-M1
- Hibernate 5.6 雅加達變體/Postgres Jdbc 驅動程式 42.3.1
- Apache Tomcat 10.0.14
要重現這些問題,請通過啟動 Postgresdocker compose up postgres并mvn clean package cargo:run -Ptomcat在專案檔案夾中運行 以部署到由貨物管理的 tomcat 服務器。
PS:我還配置了Jetty和WildFly,都運行良好。
更新:這個問題有點奇怪,因為將 Postgres jdbc 驅動程式打包到 war 中與 Spring5/Tomcat9 配合得很好。但是它不適用于Spring6/Tomcat10,我必須從war包中排除pg Jdbc驅動程式,并將其復制到tomcat/lib檔案夾中,請參閱集成測驗。
順便說一句,Java 開發人員更喜歡 Tomcat,一個原因是大多數流行的 Jdbc 驅動程式在打包成 wars 時運行良好,相比之下,過去幾年大多數傳統應用服務器都不支持它(您必須將它安裝到應用程式中)服務器通過應用程式服務器命令列工具或管理控制臺)。但是從 Java EE 7 開始,它允許開發人員定義應用程式范圍的DataSources(via @DataSourceDefinition) 并將 Jdbc 驅動程式直接打包到應用程式 war 包中,當應用程式部署時,它會自動注冊 Jdbc 驅動程式。不知道為什么最新的 Tomcat 會增加開發的復雜性并使用舊的應用服務器方法。
uj5u.com熱心網友回復:
簡短的回答:在你的DataSourceConfig課堂上你不打電話DriverManagerDataSource#setDriverClassName,因此DriverManager不知道在哪里可以找到適合jdbc:postgresql:URI 的驅動程式。
長答案:等等,我真的需要指定驅動程式的類名嗎,不是自動檢測到 JDBC 驅動程式嗎?是的,從 Java 6 和 JDBC 4 開始,JDBC 驅動程式會通過該ServiceLoader機制自動檢測。
但是,在第一次呼叫DriverManager.getDrivers(). Tomcat 確保這發生在服務器的類路徑中(參見JreMemoryLeakPrevention),因此只注冊全域安裝的驅動程式(系統類加載器不持有對應用程式類加載器的參考)。
因此,您可以:
- 在服務器的類路徑(例如
$CATALINA_BASE/lib)中安裝 PostgreSQL JDBC 驅動程式并將其從應用程式中洗掉, - 或確保在您的應用程式啟動時加載驅動程式(并在停止時取消注冊):
Class.forName("org.postgresql.Driver"); - 您還可以模擬用于
DriverManager注冊與您的應用程式一起分發的所有驅動程式的自動發現機制:private static void registerJdbcDrivers(ServletContext context) { final ServiceLoader<Driver> serviceLoader = ServiceLoader.load(Driver.class, context.getClassLoader()); final Iterator<Driver> iter = serviceLoader.iterator(); while (iter.hasNext()) { // Just for the side-effect of loading the class and registering the driver iter.next(); } }
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/403734.html
標籤:
下一篇:axios較常用的全域配置
