在 WEB-INF 目录中嵌入 H2 数据库
Embedding an H2 Database within the WEB-INF Directory
我有一个嵌入式 H2 数据库,我想将其放入 Web 应用程序的 WEB-INF 目录中。
在 JDBC url 中引用它的正确方法是什么?
理想情况下,我想要一个既适用于 WAR 又适用于扩展 WAR(如果可能)的解决方案。
感谢您的帮助!
仅供参考,我尝试了以下方法:
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;CIPHER=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应用程序deployed/started时就打开嵌入式H2数据库,并在应用程序停止时正确关闭。
为了执行此操作,需要使用侦听器。这是我提议的对我之前的回答的更新。这次解决方案使用 AES CIPHER 完成,应该很容易插入您的代码。
建议:侦听器java代码可以很容易地修改以启动H2 tcp服务器,对启用自动混合模式(嵌入式+tcp)很有用。
在文件中添加 3 行 web.xml:
<listener>
<listener-class>com.mine.MyServletContextListener</listener-class>
</listener>
文件MyServletContextListener.java:
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 {
}
}
}
我有一个嵌入式 H2 数据库,我想将其放入 Web 应用程序的 WEB-INF 目录中。
在 JDBC url 中引用它的正确方法是什么?
理想情况下,我想要一个既适用于 WAR 又适用于扩展 WAR(如果可能)的解决方案。
感谢您的帮助!
仅供参考,我尝试了以下方法:
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;CIPHER=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应用程序deployed/started时就打开嵌入式H2数据库,并在应用程序停止时正确关闭。
为了执行此操作,需要使用侦听器。这是我提议的对我之前的回答的更新。这次解决方案使用 AES CIPHER 完成,应该很容易插入您的代码。
建议:侦听器java代码可以很容易地修改以启动H2 tcp服务器,对启用自动混合模式(嵌入式+tcp)很有用。
在文件中添加 3 行 web.xml:
<listener>
<listener-class>com.mine.MyServletContextListener</listener-class>
</listener>
文件MyServletContextListener.java:
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 {
}
}
}