Jdbc 在WEB-INF目录中嵌入H2数据库
我有一个嵌入式H2数据库,我想放在WEB应用程序的WEB-INF目录中 在JDBCURL中引用这个的正确方法是什么 理想情况下,我想要一个既适用于战争又适用于扩大战争(如果可能)的解决方案 谢谢你的帮助 仅供参考,我尝试了以下方法:Jdbc 在WEB-INF目录中嵌入H2数据库,jdbc,h2,web-inf,Jdbc,H2,Web Inf,我有一个嵌入式H2数据库,我想放在WEB应用程序的WEB-INF目录中 在JDBCURL中引用这个的正确方法是什么 理想情况下,我想要一个既适用于战争又适用于扩大战争(如果可能)的解决方案 谢谢你的帮助 仅供参考,我尝试了以下方法: jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES 但这导致: org.h2.jdbc.JdbcSQLException: A file path that is implicitly relative to the current wor
jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES
但这导致:
org.h2.jdbc.JdbcSQLException: A file path that is implicitly relative to the current working directory is not allowed in the database URL "jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES". Use an absolute path, ~/name, ./name, or the baseDir setting instead. [90011-187]
将此更改为:
jdbc:h2:./WEB-INF/data/myDB;密码=AES
导致以下错误,这清楚地表明它试图将我的数据库放在Tomcat的bin目录中,而不是我想要的真正的WEB-INF目录中:
org.h2.jdbc.JdbcSQLException: Error while creating file "C:/Program Files/Apache Software Foundation/Tomcat 7.0/bin/WEB-INF" [90062-187]
我成功地使嵌入式解决方案在没有AES的情况下工作,如下所示:
try {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:h2:" + getServletContext().getRealPath("/") +
"/WEB-INF/data/myDB", "sa", "");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TABLES");
while (rs.next()) {
}
rs.close();
stmt.close();
conn.close();
} catch(SQLException e) {
} catch(ClassNotFoundException e) {
} finally {
}
这是在Tomcat8上用H2 1.3.176测试的。它应该与H2 1.4和CIPHER=AES
一起工作,前提是嵌入式数据库已经在war文件中
其思想如下:您需要获得绝对路径,部署路径可能不同,具体取决于您如何部署war文件
因此,我们需要使用servlet上下文并请求实际路径。为此,我们使用getServletContext().getRealPath(“/”)
,并根据您的需要向其追加/WEB-INF/data/myDB
我没有测试CIPHER=AES
部分,因为我从未使用过它
更新:
获取对servlet上下文的良好引用是一件棘手的事情。可以使用原始请求,获取底层会话,然后访问servlet上下文
但最好在Tomcat中部署/启动应用程序后立即打开嵌入式H2数据库,并在应用程序停止后立即正确关闭
为了实现这一点,需要使用侦听器。以下是我对先前答案的更新建议。这一次,解决方案是完整的AES密码,它应该很容易插入到您的代码
建议:可以轻松修改侦听器java代码以启动H2 tcp服务器,这对于启用自动混合模式(嵌入式+tcp)非常有用
在web.xml文件中添加3行:
根据需要支持的应用程序服务器,在将文件放入webinf时应小心。Websphere在这方面非常挑剔。您是向数据库写入还是只读?最好允许将数据库存储在单独的目录中,并允许以只读方式配置路径,并且只能在Tomcat上部署,最好是WAR格式。不允许在程序文件中写入,请尝试其他路径。我知道我不允许在程序文件中写入。WEB-INF目录也不在Tomcat的bin目录下。我要指出的错误是,相对路径没有达到预期的效果。如果示例符合实际情况,则不会有任何影响;-)@道格:最后,我没有使用servlet进入tcp模式。我想无论war扩展到何处,使用嵌入式模式都会获得更好的性能。@Doug您测试过我建议的修复程序吗?@Doug请确保将此代码放入扩展HttpServlet的类中,否则
getServletContext()
将不可用。由于我没有您的代码的完整视图,您的里程可能会有所不同…@Doug我修复了如何在不使用请求的情况下获取servlet上下文,而是使用侦听器。抱歉,我只是回到这个:-)。我通过将数据库放入内存暂时解决了这个问题,但我将切换到上下文侦听器选项。这肯定是我要寻找的更多,但是我在网上找到的上下文侦听器示例仍然没有处理WEB-INF数据库。感谢您花时间整理了一个很好的答案!
<listener>
<listener-class>com.mine.MyServletContextListener</listener-class>
</listener>
package com.mine;
import javax.servlet.*;
import java.sql.*;
public class MyServletContextListener implements ServletContextListener {
Connection conn;
public void contextInitialized(ServletContextEvent sce) {
try {
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection( "jdbc:h2:" + sce.getServletContext().getRealPath("/") + "/WEB-INF/data/myDB;CIPHER=AES", "sa", "aespassword dbpassword");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TABLES");
while (rs.next()) {
}
rs.close();
stmt.close();
} catch(SQLException e) {
} catch(ClassNotFoundException e) {
} finally {
}
}
public void contextDestroyed(ServletContextEvent sce) {
try {
conn.close();
} catch(SQLException e) {
} finally {
}
}
}