2015-05-30 20 views
6

Ho un database H2 incorporato che vorrei inserire nella directory WEB-INF di un'applicazione web.Incorporamento di un database H2 all'interno della directory WEB-INF

Qual è il modo corretto di fare riferimento a questo in un URL JDBC?

Idealmente mi piacerebbe una soluzione che avrebbe funzionato sia per una GUERRA, sia per una GUERRA ampliata (se possibile).

Grazie per il vostro aiuto!

FYI, ho provato la seguente:

jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES 

Ma questo si traduce in:

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] 

La modifica di questa a: jdbc: h2: ./ WEB-INF/dati/myDB ; CIPHER = AES

Risultati nel seguente errore, che mostra chiaramente il suo tentativo di mettere il mio database nella directory bin di Tomcat, piuttosto che la vera directory WEB-INF dove lo voglio:

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

A seconda di quale applicazione server è necessario sostenere si dovrebbe fare attenzione con la messa in file WEBINF. Websphere è molto esigente in questo settore. Scrivi nel database o è in sola lettura? È meglio consentire la memorizzazione del database in una directory separata e consentire la configurazione del percorso – Marged

+0

È di sola lettura e deve essere distribuito solo su Tomcat, preferibilmente nel formato WAR. – Doug

+0

Non è consentito scrivere nei file di programma, provare un percorso diverso – Marged

risposta

6

sono riuscito a fare il lavoro una soluzione integrata senza AES come questo:

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 { 
} 

Questo è stato testato con H2 1.3.176 su Tomcat8. Dovrebbe funzionare con H2 1.4 e CIPHER=AES a condizione che il database incorporato sia già nel file di guerra, immagino.

L'idea è la seguente: è necessario ottenere il percorso assoluto e il percorso di distribuzione potrebbe non essere lo stesso a seconda del modo in cui è stato distribuito il file di guerra.

Quindi è necessario utilizzare il contesto servlet e richiedere il percorso reale. Per questo usiamo getServletContext().getRealPath("/") e aggiungiamo /WEB-INF/data/myDB ad esso secondo le vostre esigenze.

Non ho provato la parte CIPHER=AES come non l'ho mai usata.

Aggiornamento:

Ottenere un buon riferimento al contesto servlet è difficile. Si potrebbe usare una richiesta non elaborata, ottenere la sessione sottostante e quindi accedere al contesto servlet.

Ma sarebbe bello avere il database H2 incorporato aperto non appena l'applicazione viene distribuita/avviata in Tomcat e chiusa correttamente non appena l'applicazione viene arrestata.

Per eseguire ciò, è necessario l'utilizzo di un listener. Ecco cosa propongo come aggiornamento alla mia precedente risposta. Questa volta la soluzione è completa con AES CIPHER e dovrebbe essere facile da inserire nel codice.

Suggerimento: il codice java del listener può essere facilmente modificato per avviare anche un server H2 tcp, utile per abilitare la modalità mista automatica (incorporata + tcp).

Aggiungere 3 righe al file web.xml:

<listener> 
    <listener-class>com.mine.MyServletContextListener</listener-class> 
</listener> 

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 { 
    } 

    } 

} 
+0

@Doug: alla fine non sono andato in modalità tcp con servlet. Immagino che questo ti farà ottenere prestazioni migliori usando la modalità embedded, indipendentemente da dove la guerra è stata espansa. –

+0

@Doug hai testato la mia soluzione suggerita? –

+0

@Doug Assicurati di inserire questo codice in una classe che estende HttpServlet, altrimenti '' 'getServletContext()' '' non sarà disponibile. Poiché non ho la visione completa del tuo codice, il tuo chilometraggio può variare ... –