risposta-alla-domanda-sullo-sviluppo-web-bd.com

Dove posizionare e come leggere i file di risorse di configurazione nell'applicazione basata su servlet?

Nella mia applicazione web devo inviare e-mail a set di utenti predefiniti come [email protected], quindi desidero aggiungerlo a un file .properties e accedervi quando richiesto. È una procedura corretta, se è così allora dove dovrei posizionare questo file? Sto usando Netbeans IDE che sta avendo due cartelle separate per i file sorgente e JSP.

207
sansknwoledge

È la vostra scelta. Esistono fondamentalmente tre modi in un archivio di applicazioni Web Java (WAR):


1. Inseriscilo in classpath

In modo che tu possa caricarlo ClassLoader#getResourceAsStream() con un percorso relativo al classpath:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);

Qui foo.properties deve essere inserito in una delle radici coperte dal percorso di classe predefinito di una webapp, ad es. /WEB-INF/lib e /WEB-INF/classes di webapp, /lib del server, o /lib di JDK/JRE. Se il file di proprietà è specifico per webapp, è meglio inserirlo in /WEB-INF/classes. Se stai sviluppando un progetto WAR standard in un IDE, rilasciatelo nella cartella src (la cartella di origine del progetto). Se stai usando un progetto Maven, rilasciatelo nella cartella /main/resources.

In alternativa, puoi anche metterlo da qualche parte al di fuori del classpath predefinito e aggiungere il suo percorso al classpath del server delle applicazioni. Ad esempio, in Tomcat è possibile configurarlo come proprietà shared.loader di Tomcat/conf/catalina.properties.

Se hai inserito foo.properties in una struttura di pacchetto Java come com.example, devi caricarlo come di seguito

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
// ...

Si noti che questo percorso di un caricatore di classi di contesto non deve iniziare con /. Solo quando si utilizza un caricatore di classi "relativo" come SomeClass.class.getClassLoader(), è effettivamente necessario avviarlo con un /.

ClassLoader classLoader = getClass().getClassLoader();
InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
// ...

Tuttavia, la visibilità del file delle proprietà dipende dal caricatore di classe in questione. È visibile solo con lo stesso programma di caricamento classe di quello che ha caricato la classe. Quindi, se la classe viene caricata da ad es. server comune classloader invece di webapp classloader, e il file delle proprietà si trova all'interno della webapp stessa, quindi è invisibile. Il loader della classe di contesto è la tua scommessa più sicura in modo da poter posizionare il file delle proprietà "ovunque" nel classpath e/o si intende essere in grado di sovrascrivere quello fornito dal server sulla webapp.


2. Inseriscilo in webcontent

In modo che tu possa caricarlo ServletContext#getResourceAsStream() con un percorso relativo al webcontent:

InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
// ...

Nota che ho dimostrato di posizionare il file nella cartella /WEB-INF, altrimenti sarebbe stato accessibile al pubblico da qualsiasi browser. Si noti inoltre che ServletContext si trova in qualsiasi classe HttpServlet accessibile solo dall'ereditarietà GenericServlet#getServletContext() e in Filter di FilterConfig#getServletContext() . Nel caso in cui non sei in una classe servlet, di solito è solo iniettabile tramite @Inject.


3. Mettilo nel file system del disco locale

In modo che tu possa caricarlo il solito modo Java.io con un percorso assoluto del file system del disco locale:

InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...

Nota l'importanza di utilizzare un percorso assoluto. I percorsi relativi al file system del disco locale sono un assoluto non-go in un'applicazione web Java EE. Vedi anche il primo link "Vedi anche" qui sotto.


Quale scegliere?

Basta valutare i vantaggi/gli svantaggi di la propria opinione sulla manutenibilità.

Se i file delle proprietà sono "statici" e non devono mai essere modificati durante il runtime, è possibile conservarli in WAR.

Se si preferisce essere in grado di modificare i file di proprietà dall'esterno dell'applicazione Web senza la necessità di ricostruire e ridistribuire il WAR ogni volta, quindi inserirlo nel classpath all'esterno del progetto (se necessario aggiungere la directory al classpath).

Se si preferisce essere in grado di modificare i file di proprietà a livello di codice dall'interno dell'applicazione Web utilizzando il metodo Properties#store(), posizionarlo all'esterno dell'applicazione Web. Poiché Properties#store() richiede un Writer, non è possibile aggirare l'utilizzo di un percorso del file system del disco. Tale percorso può a sua volta essere passato all'applicazione web come argomento VM o proprietà di sistema. Come precauzione, mai usa getRealPath() . Tutte le modifiche nella cartella di distribuzione andranno perse in una ridistribuzione per il semplice motivo che le modifiche non si riflettono nel file WAR originale.

Guarda anche:

445
BalusC

Parola di avvertimento: se metti i file di configurazione nella tua cartella WEB-INF/classes e il tuo IDE, ad esempio Eclipse, esegue un clean/rebuild, eseguirà il nuke dei tuoi file conf a meno che non siano nella directory dei sorgenti Java. La grande risposta di BalusC allude a questo nell'opzione 1, ma volevo aggiungere enfasi.

Ho imparato a fondo che se si "copia" un progetto Web in Eclipse, si esegue una pulizia/ricostruzione da qualsiasi cartella di origine. Nel mio caso ho aggiunto una "dir fonte collegata" dalla nostra libreria Java POJO, che si sarebbe compilata nella cartella WEB-INF/classes. Fare una pulizia/ricostruzione in quel progetto (non nel progetto dell'app Web) ha causato lo stesso problema.

Ho pensato di mettere i miei confs nella cartella src POJO, ma questi conf sono tutti per librerie di terze parti (come Quartz o URLRewrite) che si trovano nella cartella WEB-INF/lib, quindi non aveva senso. Ho intenzione di provare a metterlo nella cartella "src" dei progetti web quando ci arrivo, ma quella cartella è al momento vuota e avere file di configurazione in esso sembra inelegante.

Quindi voto per mettere i file conf in WEB-INF/commonConfFolder/filename.properties, next nella cartella classes, che è l'opzione Balus 2.

8
Ed Pike

Es .: nel file web.xml il tag

<context-param>
        <param-name>chatpropertyfile</param-name>
        <!--  Name of the chat properties file. It contains the name and description                   of rooms.-->     
        <param-value>chat.properties</param-value>
    </context-param>

E chat.properties puoi dichiarare le tue proprietà in questo modo

Per esempio:

Jsp = Discussion about JSP can be made here.
Java = Talk about Java and related technologies like J2EE.
ASP = Discuss about Active Server Pages related technologies like VBScript and JScript etc.
Web_Designing = Any discussion related to HTML, JavaScript, DHTML etc.
StartUp = Startup chat room. Chatter is added to this after he logs in.
6
Subhash Pavuskar

Deve solo essere nel classpath (ovvero assicurarsi che finisca sotto/WEB-INF/classes nel file .war come parte della build).

5
Taylor Leese

Puoi farlo con la tua cartella sorgente così ogni volta che costruisci, quei file vengono copiati automaticamente nella directory classes.

Invece di usare il file delle proprietà, usa il file XML.

Se i dati sono troppo piccoli, puoi anche usare web.xml per accedere alle proprietà.

Tieni presente che qualsiasi di questi approcci richiederà il riavvio del server delle app per riflettere le modifiche.

3
Kalpak

Supponiamo che il tuo codice cerchi il file dire app.properties. Copia questo file in qualsiasi directory e aggiungi questa dir a classpath, creando un setenv.sh nella directory bin di Tomcat.

Nel setenv.sh di Tomcat (se questo file non esiste, creane uno, Tomcat carica questo file setenv.sh. #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"

Non dovresti avere i tuoi file di proprietà in ./webapps//WEB-INF/classes/app.properties

Il caricatore di classi Tomcat sovrascriverà quello di WEB-INF/classes /

Una buona lettura: https://Tomcat.Apache.org/Tomcat-8.0-doc/class-loader-howto.html

1
Thar