2015-05-30 2 views
6

У меня есть встроенная база данных H2, которую я хотел бы поместить в каталог WEB-INF веб-приложения.Внедрение базы данных H2 в каталоге WEB-INF

Каков правильный способ обращения к этому в URL-адресе JDBC?

В идеале я бы хотел найти решение, которое будет работать как для WAR, так и для расширенной WAR (если возможно).

Благодарю вас за помощь!

FYI, я попытался следующие:

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/данные/MyDB ; CIPHER = AES

Приводит к следующей ошибке, в которой ясно показано, как она пытается поместить мою базу данных в каталог bin в Tomcat, а не в настоящий каталог WEB-INF, где я хочу:

org.h2.jdbc.JdbcSQLException: Error while creating file "C:/Program Files/Apache Software Foundation/Tomcat 7.0/bin/WEB-INF" [90062-187] 
+0

В зависимости от того, какие приложения сервера вам нужно будет поддерживать, вы должны быть осторожны с введением файлов в webinf. Websphere очень разборчива в этой области. Вы пишете в базу данных или читаете? Лучше разрешить сохранение базы данных в отдельном каталоге и разрешить конфигурацию пути – Marged

+0

Его доступность только для чтения и должна быть развернута только на Tomcat, предпочтительно в формате WAR. – Doug

+0

Вам не разрешено писать файлы программы, попробуйте другой путь – Marged

ответ

6

мне удалось сделать внедренный работу решение без 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 { 
} 

Это было проверено с Н2 1.3.176 на Tomcat8. Он должен работать с H2 1.4 и CIPHER=AES, если встроенная база данных уже находится в файле войны, я думаю.

Идея заключается в следующем: вам необходимо получить абсолютный путь, и этот путь развертывания может отличаться от того, как вы развернули военный файл.

Поэтому нам нужно использовать контекст сервлета и запросить реальный путь. Для этого мы используем getServletContext().getRealPath("/") и добавим /WEB-INF/data/myDB к нему в соответствии с вашими потребностями.

Я не тестировал часть CIPHER=AES, поскольку я ее никогда не использовал.

Update:

Получение хорошей ссылки на контекст сервлета сложен. Можно использовать необработанный запрос, получить базовый сеанс, а затем перейти к контексту сервлета.

Но было бы хорошо, если бы встроенная база данных H2 открывалась, как только приложение было развернуто/запущено в Tomcat и закрыто правильно, как только приложение будет остановлено.

Для этого необходимо использовать прослушиватель. Вот что я предлагаю в качестве обновления моего предыдущего ответа. На этот раз решение в комплекте с AES CIPHER, и его легко подключить к вашему коду.

Предложение: Java-код слушателя может быть легко изменен для запуска сервера H2 tcp, который также полезен для включения автоматического смешанного режима (встроенный + tcp).

Добавить 3 строки в файл в Интернете.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 { 
    } 

    } 

} 
+0

@Doug: в конце концов я не пошел в режиме tcp с сервлетом. Я предполагаю, что это даст вам лучшие результаты, используя встроенный режим, независимо от того, где была расширена война. –

+0

@ Doug вы проверили мое предложенное исправление? –

+0

@Doug Пожалуйста, убедитесь, что вы поместите этот код в класс, расширяющий HttpServlet, иначе '' '' getServletContext() '' 'будет недоступен. Поскольку у меня нет полного представления о вашем коде, ваш пробег может меняться ... –