Wo platzieren und wie werden Konfigurationsressourcendateien in einer servletbasierten Anwendung gelesen?

222

In meiner Webanwendung muss ich E-Mails an eine Reihe vordefinierter Benutzer senden [email protected], daher möchte ich diese einer .propertiesDatei hinzufügen und bei Bedarf darauf zugreifen. Ist dies ein korrektes Verfahren? Wenn ja, wo soll ich diese Datei ablegen? Ich verwende Netbeans IDE, die zwei separate Ordner für Quell- und JSP-Dateien hat.

sansknwoledge
quelle
JNDI könnte vielleicht eine Lösung sein?
Basil Bourque

Antworten:

464

Es ist deine Wahl. Grundsätzlich gibt es in einem Java-Webanwendungsarchiv (WAR) drei Möglichkeiten:


1. Legen Sie es in den Klassenpfad

Damit Sie es ClassLoader#getResourceAsStream()mit einem klassenpfadbezogenen Pfad laden können :

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

Hier foo.propertiessoll in einer der Wurzeln platziert werden, die durch den Standardklassenpfad einer Webanwendung abgedeckt sind, z. B. Webanwendungen /WEB-INF/libund /WEB-INF/classesServer /liboder JDK / JREs /lib. Wenn die Eigenschaftendatei webapp-spezifisch ist, platzieren Sie sie am besten in /WEB-INF/classes. Wenn Sie ein Standard-WAR-Projekt in einer IDE entwickeln, legen Sie es im srcOrdner (dem Quellordner des Projekts) ab. Wenn Sie ein Maven-Projekt verwenden, legen Sie es im /main/resourcesOrdner ab.

Alternativ können Sie es auch außerhalb des Standardklassenpfads platzieren und seinen Pfad zum Klassenpfad des Anwendungsservers hinzufügen. In beispielsweise Tomcat können Sie es als shared.loaderEigenschaft von konfigurieren Tomcat/conf/catalina.properties.

Wenn Sie foo.propertieses in einer Java-Paketstruktur wie platziert haben com.example, müssen Sie es wie folgt laden

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

Beachten Sie, dass dieser Pfad eines Kontextklassenladers nicht mit a beginnen sollte /. Nur wenn Sie einen "relativen" Klassenlader wie verwenden SomeClass.class.getClassLoader(), müssen Sie ihn tatsächlich mit einem starten /.

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

Die Sichtbarkeit der Eigenschaftendatei hängt dann jedoch vom jeweiligen Klassenladeprogramm ab. Es ist nur für denselben Klassenlader sichtbar wie derjenige, der die Klasse geladen hat. Wenn die Klasse also von einem allgemeinen Server-Klassenlader anstelle eines Webapp-Klassenladers geladen wird und sich die Eigenschaftendatei in der Webapp selbst befindet, ist sie unsichtbar. Der Kontextklassenlader ist Ihre sicherste Wahl, damit Sie die Eigenschaftendatei "überall" im Klassenpfad platzieren können und / oder beabsichtigen, eine vom Server bereitgestellte Datei aus der Webanwendung zu überschreiben.


2. Legen Sie es in Webinhalt

Damit Sie es von laden können ServletContext#getResourceAsStream() mit einem webinhaltsbezogenen Pfad :

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

Beachten Sie, dass ich demonstriert habe, die Datei in einem /WEB-INFOrdner abzulegen, da sie sonst für jeden Webbrowser öffentlich zugänglich gewesen wäre. Beachten Sie auch, dass das ServletContextin jeder HttpServletKlasse nur für die geerbten GenericServlet#getServletContext()und in Filtervon zugänglich istFilterConfig#getServletContext() . Wenn Sie nicht in einer Servlet-Klasse sind, kann diese normalerweise nur über injiziert werden @Inject.


3. Legen Sie es in das lokale Datenträger-Dateisystem

Damit Sie es wie gewohnt java.iomit einem absoluten lokalen Datenträger-Dateisystempfad laden können :

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

Beachten Sie, wie wichtig es ist, einen absoluten Pfad zu verwenden. Relative lokale Datenträger-Dateisystempfade sind in einer Java EE-Webanwendung ein absolutes No-Go. Siehe auch den ersten Link "Siehe auch" unten.


Welche soll ich wählen?

Wägen Sie einfach die Vor- und Nachteile in Ihrem eigenen Meinung zur Wartbarkeit ab.

Wenn die Eigenschaftendateien "statisch" sind und zur Laufzeit nie geändert werden müssen, können Sie sie in der WAR behalten.

Wenn Sie es vorziehen, Eigenschaftendateien von außerhalb der Webanwendung bearbeiten zu können, ohne die WAR jedes Mal neu erstellen und erneut bereitstellen zu müssen, fügen Sie sie in den Klassenpfad außerhalb des Projekts ein (fügen Sie gegebenenfalls das Verzeichnis dem Klassenpfad hinzu).

Wenn Sie es vorziehen, Eigenschaftendateien mithilfe der Properties#store()Methode programmgesteuert aus der Webanwendung heraus bearbeiten zu können , legen Sie sie außerhalb der Webanwendung ab. Da dies Properties#store()erforderlich ist Writer, können Sie keinen Datenträger-Dateisystempfad verwenden. Dieser Pfad kann wiederum als VM-Argument oder Systemeigenschaft an die Webanwendung übergeben werden. Verwenden Sie vorsichtshalber niemalsgetRealPath() . Alle Änderungen im Bereitstellungsordner gehen bei einer erneuten Bereitstellung verloren, da die Änderungen nicht in der ursprünglichen WAR-Datei wiedergegeben werden.

Siehe auch:

BalusC
quelle
2
"Ich persönlich bevorzuge es, es in den Klassenpfad außerhalb des Projekts einzufügen (neuen Pfad zum Klassenpfad hinzufügen)" verwirrt, können Sie ein Beispiel geben?
Blankman
4
@Blankman Er bedeutet wahrscheinlich, einen neuen Ordner zu erstellen, alle Ihre benutzerdefinierten Konfigurationsdateien dort abzulegen und diesen Ordner dem Klassenpfad hinzuzufügen. Also: 1) Erstellen Sie irgendwo einen Ordner mit dem Namen 'appconfs' (möglicherweise sogar /etc/appconfs2). Fügen Sie diesen Ordner dem Klassenpfad von App Server / Domain hinzu. Der zweite Schritt ist App-Server-spezifisch. Ich glaube nicht, dass es dafür ein generisches Beispiel gibt.
Tuukka Mustonen
Betreff: 2: Warum sollten beide "WEB-INF/filename.properties"und "/WEB-INF/filename.properties"( /am Anfang beachten ) funktionieren? Gibt es einen Grund, einen dem anderen vorzuziehen?
Mr_and_Mrs_D
Ich bin seit einem Tag in diesem Problem behoben. Ich kann meine Eigenschaftendatei nicht laden. Ich kann es von zwei Stellen laden. Eines ist das Systemverzeichnis und eines ist das lokale Laufwerk. Es funktioniert mit localhost. Aber ich möchte es auf Amazon bereitstellen.
Arun Raja
Ich verwende die NetBeans-IDE und behalte die Eigenschaftendatei in Webseiten / Ressourcen. Ich versuche, als "./Web Pages / resources / config.properties" darauf zuzugreifen. Ich kann nicht darauf zugreifen. Bitte hilf mir.
Arun Raja
9

Ein Wort der Warnung: Wenn Sie Konfigurationsdateien in Ihren WEB-INF/classesOrdner legen und Ihre IDE, z. B. Eclipse, eine Bereinigung / Neuerstellung durchführt, werden Ihre Conf-Dateien zerstört, sofern sie sich nicht im Java-Quellverzeichnis befinden. Die großartige Antwort von BalusC spielt in Option 1 darauf an, aber ich wollte die Betonung hinzufügen.

Ich habe auf die harte Tour gelernt, dass ein Webprojekt, das in Eclipse "kopiert" wird, aus allen Quellordnern bereinigt / neu erstellt wird. In meinem Fall hatte ich ein "verknüpftes Quellverzeichnis" aus unserer POJO-Java-Bibliothek hinzugefügt, das in den WEB-INF/classesOrdner kompiliert wurde . Das Bereinigen / Wiederherstellen in diesem Projekt (nicht im Web-App-Projekt) verursachte das gleiche Problem.

Ich habe darüber nachgedacht, meine Confs in den Ordner POJO src zu legen, aber diese Confs sind alle für Bibliotheken von Drittanbietern (wie Quartz oder URLRewrite), die sich im WEB-INF/libOrdner befinden, sodass dies keinen Sinn ergab. Ich habe vor, zu testen, ob ich es in den Ordner "src" von Webprojekten lege, wenn ich dazu komme, aber dieser Ordner ist derzeit leer und es scheint unelegant, Conf-Dateien darin zu haben.

Also ich Abstimmung für die Umsetzung conf Dateien in WEB-INF/commonConfFolder/filename.properties, neben den Klassen - Ordner, der 2 Balus Option.

Ed Pike
quelle
1
Wenn Sie Ihre Konfigurationsdatei in einem Unterordner von WEB_INF ablegen, wie erreichen Sie sie dann? Ich hatte kein Glück mit sagen 'configFiles / prop.properties'
JesseBoyd
OK, das funktioniert. Wenn Sie die Eigenschaftendatei unter 'Java Resources / src /' platzieren, funktioniert dies nicht in einem meiner Pakete und muss sich im Stammverzeichnis von src befinden. Ihre Warnung, dass der Klassenordner zerstört wird, ist ein berechtigtes Anliegen.
JesseBoyd
6

Beispiel: In der Datei web.xml das 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>

Und chat.properties können Sie Ihre Eigenschaften so deklarieren

Zum Beispiel:

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.
Subhash Pavuskar
quelle
5

Es muss sich nur im Klassenpfad befinden (auch bekannt als sicherstellen, dass es als Teil des Builds unter / WEB-INF / classes in .war landet).

Taylor Leese
quelle
Hallo, danke für die Idee, aber es sagt mir, dass die angegebene Datei nicht gefunden werden kann. Ja, es ist das
Pfadproblem,
3

Sie können dies mit Ihrem Quellordner tun, sodass diese Dateien beim Erstellen automatisch in das Klassenverzeichnis kopiert werden.

Verwenden Sie anstelle der Eigenschaftendatei die XML-Datei.

Wenn die Daten zu klein sind, können Sie sogar web.xml für den Zugriff auf die Eigenschaften verwenden.

Bitte beachten Sie, dass für jeden dieser Ansätze ein Neustart des App-Servers erforderlich ist, damit die Änderungen übernommen werden.

Kalpak
quelle
Ich habe in den Webseiten-Ordner gelegt, aber nicht auf die Datei zugreifen Datei nicht gefunden Fehler kommt, wie man Pfad
Sansknwoledge
1
Wenn Ihre Datei im Ordner WEB-INF / classes landet, wird sie automatisch in den Klassenpfad gesetzt
Kalpak
2

Angenommen, Ihr Code sucht nach der Datei app.properties. Kopieren Sie diese Datei in ein beliebiges Verzeichnis und fügen Sie dieses Verzeichnis dem Klassenpfad hinzu, indem Sie eine setenv.sh im bin-Verzeichnis von tomcat erstellen.

In Ihrer setenv.sh von tomcat (wenn diese Datei nicht vorhanden ist, erstellen Sie eine, lädt tomcat diese setenv.sh-Datei. #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"

Sie sollten Ihre Eigenschaftendateien nicht in ./webapps//WEB-INF/classes/app.properties haben

Der Tomcat-Klassenlader überschreibt den mit dem von WEB-INF / classes /

Eine gute Lektüre: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

Thar
quelle