将H2数据库嵌入WEB-INF目录中 [英] Embedding an H2 Database within the WEB-INF Directory
问题描述
我有一个嵌入式H2数据库,我想将其放置在Web应用程序的WEB-INF目录中.
I have an embedded H2 Database I'd like to put in the WEB-INF directory of a web application.
在JDBC网址中引用此内容的正确方法是什么?
What is the proper way to refer to this in a JDBC url?
理想情况下,我想要一个既适用于WAR,又适用于扩展的WAR(如果可能)的解决方案.
Ideally I'd like a solution that would work both for a WAR, and an expanded WAR (If possible).
谢谢您的帮助!
仅供参考,我尝试了以下操作:
FYI, I've tried the following:
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
Changing this to: jdbc:h2:./WEB-INF/data/myDB;CIPHER=AES
导致以下错误,这清楚地表明了它试图将我的数据库放置在Tomcat的bin目录中,而不是我想要的真实WEB-INF目录中的情况:
Results in the following error, which clearly shows its trying to put my database in Tomcat's bin directory, rather than the true WEB-INF directory where I want it:
org.h2.jdbc.JdbcSQLException: Error while creating file "C:/Program Files/Apache Software Foundation/Tomcat 7.0/bin/WEB-INF" [90062-187]
推荐答案
我设法使嵌入式解决方案在没有AES的情况下工作,如下所示:
I managed to make the embedded solution work without AES like this:
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进行了测试.只要嵌入式数据库已经在war文件中,它就可以与H2 1.4和CIPHER=AES
一起使用.
This was tested with H2 1.3.176 on Tomcat8. It should work with H2 1.4 and CIPHER=AES
provided the embedded database is already inside the war file I guess.
这个想法是这样的:您需要获取绝对路径,并且根据您部署war文件的方式,部署路径可能会有所不同.
The idea is the following: you need to get the absolute path, and that deployment path may not be the same depending on how you deployed the war file.
因此,我们需要使用servlet上下文并请求真实路径.为此,我们使用getServletContext().getRealPath("/")
并根据您的需要在其后附加/WEB-INF/data/myDB
.
So we need to use the servlet context and request the real path. For this we use getServletContext().getRealPath("/")
and append /WEB-INF/data/myDB
to it as per your needs.
我从未测试过CIPHER=AES
部分,因为我从未使用过它.
I did not test the CIPHER=AES
part as I've never used it.
更新:
要获得对Servlet上下文的良好引用非常棘手.可以使用原始请求,获取基础会话,然后到达servlet上下文.
Getting a good reference to the servlet context is tricky. One could use a raw request, get the underlying session and then get to the servlet context.
但是最好在Tomcat中部署/启动应用程序后立即打开嵌入式H2数据库,并在应用程序停止后立即正确关闭嵌入式H2数据库.
But it would be good to have the embedded H2 database opened as soon as the application is deployed/started in Tomcat, and closed properly as soon as the application is stopped.
为了执行该操作,需要使用侦听器.这是我对以前答案的更新建议.这次,该解决方案已使用AES CIPHER完善,应该可以轻松插入您的代码中.
In order to perform that, the use of a listener is needed. Here's what I propose as an update to my previous answer. This time the solution is complete with AES CIPHER and it should be easy to plug into your code.
建议:侦听器Java代码也可以轻松修改以启动H2 tcp服务器,这对于启用自动混合模式(嵌入式+ tcp)很有用.
Suggestion: the listener java code can be easily modified to start a H2 tcp server as well, useful to enable the automatic mixed mode (embedded+tcp).
在文件web.xml中添加3行:
Add 3 lines to the file web.xml:
<listener>
<listener-class>com.mine.MyServletContextListener</listener-class>
</listener>
文件MyServletContextListener.java:
File 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-INF目录中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!