web-dev-qa-db-fra.com

Où placer et comment lire les fichiers de ressources de configuration dans une application basée sur un servlet?

Dans mon application Web, je dois envoyer un courrier électronique à un ensemble d'utilisateurs prédéfinis comme [email protected], je souhaite donc l'ajouter à un fichier .properties et y accéder si nécessaire. Est-ce une procédure correcte, si oui, où devrais-je placer ce fichier? J'utilise Netbeans IDE qui contient deux dossiers distincts pour les fichiers source et JSP.

209
sansknwoledge

C'est ton choix. Il existe essentiellement trois méthodes d'archivage d'une application Web (WAR) Java:


1. Mettez-le en classe

Pour que vous puissiez le charger par ClassLoader#getResourceAsStream() avec un chemin relatif au chemin d'accès aux classes:

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

Ici _foo.properties_ est supposé être placé dans l’une des racines couvertes par le chemin de classe par défaut d’une webapp, par exemple. webapp's _/WEB-INF/lib_ et _/WEB-INF/classes_, serveur _/lib_ ou JDK/JRE's _/lib_. Si le fichier de propriétés est spécifique à une application Web, le mieux est de le placer dans _/WEB-INF/classes_. Si vous développez un projet WAR standard dans un IDE, déposez-le dans le dossier src (le dossier source du projet). Si vous utilisez un projet Maven, déposez-le dans le dossier _/main/resources_.

Vous pouvez également le placer quelque part en dehors du chemin de classe par défaut et ajouter son chemin au chemin de classe du serveur d'applications. Dans Tomcat par exemple, vous pouvez le configurer comme propriété _shared.loader_ de _Tomcat/conf/catalina.properties_.

Si vous avez placé le _foo.properties_ dans une structure de package Java telle que _com.example_, vous devez le charger comme ci-dessous.

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

Notez que ce chemin d'un chargeur de classe de contexte ne doit pas commencer par un _/_. Ce n'est que lorsque vous utilisez un chargeur de classe "relatif" tel que SomeClass.class.getClassLoader() que vous devez le démarrer avec un _/_.

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

Cependant, la visibilité du fichier de propriétés dépend alors du chargeur de classe en question. Il n'est visible que par le même chargeur de classe que celui qui a chargé la classe. Donc, si la classe est chargée par exemple classloader serveur commun au lieu de classloader webapp, et le fichier de propriétés est à l'intérieur de webapp lui-même, alors il est invisible. Le chargeur de classe de contexte est votre pari le plus sûr. Vous pouvez donc placer le fichier de propriétés "partout" dans le chemin de classe et/ou vous souhaitez pouvoir remplacer un fichier fourni par le serveur à partir de l'application Web.


2. Mettez-le dans le contenu Web

Pour que vous puissiez le charger par ServletContext#getResourceAsStream() avec un chemin relatif au contenu Web:

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

Notez que j'ai démontré que le fichier était placé dans le dossier _/WEB-INF_, sinon il aurait été accessible au public par n'importe quel navigateur Web. Notez également que la ServletContext est dans toute classe HttpServlet uniquement accessible par l'héritage GenericServlet#getServletContext() et dans Filter par FilterConfig#getServletContext() . Si vous n'êtes pas dans une classe de servlet, elle est généralement simplement injectable via _@Inject_.


3. Mettez-le dans le système de fichiers du disque local

Pour que vous puissiez le charger de la manière habituelle _Java.io_ avec un chemin de système de fichiers absolu sur disque local:

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

Notez l'importance d'utiliser un chemin absolu. Les chemins de système de fichiers relatifs au disque local sont une solution absolue dans une application Web Java EE. Voir aussi le premier lien "Voir aussi" ci-dessous.


Lequel choisir?

Il suffit de peser les avantages/inconvénients de votre propre opinion sur la maintenabilité.

Si les fichiers de propriétés sont "statiques" et qu'il n'est jamais nécessaire de les modifier pendant l'exécution, vous pouvez les conserver dans le fichier WAR.

Si vous préférez pouvoir modifier les fichiers de propriétés en dehors de l'application Web sans avoir à reconstruire et redéployer le fichier WAR à chaque fois, placez-le dans le chemin de classe en dehors du projet (si nécessaire, ajoutez le répertoire au chemin de classe).

Si vous préférez pouvoir modifier des fichiers de propriétés par programme à partir de l'intérieur de l'application Web à l'aide de la méthode Properties#store(), placez-le en dehors de l'application Web. Comme la Properties#store() nécessite un Writer, vous ne pouvez pas utiliser un chemin de système de fichiers sur disque. Ce chemin peut à son tour être transmis à l'application Web sous la forme d'un argument ou d'une propriété système VM. Par précaution, jamais utilisez getRealPath() . Toutes les modifications apportées au dossier de déploiement seront perdues lors d'un redéploiement pour la simple raison que les modifications ne sont pas reflétées dans le fichier WAR d'origine.

Voir également:

451
BalusC

Mise en garde: si vous mettez des fichiers de configuration dans votre dossier WEB-INF/classes et que votre IDE, disons Eclipse, effectue un nettoyage/reconstruction, il supprimera vos fichiers de configuration à moins qu'ils ne se trouvent dans la source Java annuaire. La réponse géniale de BalusC fait allusion à celle de l'option 1, mais je voulais insister davantage.

J'ai appris à mes dépens que si vous "copiez" un projet Web dans Eclipse, il effectue un nettoyage/reconstruction à partir de n'importe quel dossier source. Dans mon cas, j’avais ajouté un "répertoire source lié" de notre bibliothèque POJO Java, qui serait compilé dans le dossier WEB-INF/classes. Faire un nettoyage/reconstruction dans ce projet (pas le projet d'application Web) a causé le même problème.

J'ai pensé mettre mes confs dans le dossier src de POJO, mais ces confs sont tous pour des bibliothèques tierces (comme Quartz ou URLRewrite) qui sont dans le dossier WEB-INF/lib, ce qui n'a donc aucun sens. Je prévois de le mettre dans le dossier "src" des projets Web lorsque j'aurai accès à ce dossier, mais ce dossier est actuellement vide et contient des fichiers de configuration qui semblent inélégants.

Je vote donc pour mettre les fichiers de configuration dans WEB-INF/commonConfFolder/filename.properties, next dans le dossier classes, qui correspond à l'option 2 de Balus.

8
Ed Pike

Ex: Dans le fichier web.xml, la balise

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

Et chat.properties, vous pouvez déclarer vos propriétés comme ceci

Pour Ex:

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

Il doit juste être dans le classpath (c’est-à-dire s’assurer qu’il se termine sous/WEB-INF/classes dans le fichier .war dans le cadre de la construction).

5
Taylor Leese

Vous pouvez utiliser votre dossier source pour que, chaque fois que vous compilez, ces fichiers soient automatiquement copiés dans le répertoire classes.

Au lieu d'utiliser un fichier de propriétés, utilisez un fichier XML.

Si les données sont trop petites, vous pouvez même utiliser web.xml pour accéder aux propriétés.

Veuillez noter que l'une ou l'autre de ces approches nécessitera un redémarrage du serveur d'applications pour que les modifications soient prises en compte.

3
Kalpak

Supposons que votre code recherche le fichier dit app.properties. Copiez ce fichier dans n’importe quel répertoire et ajoutez-le à classpath en créant un fichier setenv.sh dans le répertoire bin de Tomcat.

Dans votre setenv.sh de Tomcat (si ce fichier n'existe pas, créez-en un, Tomcat chargera ce fichier setenv.sh. #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"

Vous ne devriez pas avoir vos fichiers de propriétés dans ./webapps//WEB-INF/classes/app.properties

Le chargeur de classe Tomcat remplacera celui de WEB-INF/classes /

Une bonne lecture: https://Tomcat.Apache.org/Tomcat-8.0-doc/class-loader-howto.html

1
Thar