Gdzie umieścić i jak odczytać pliki zasobów konfiguracyjnych w aplikacji opartej na serwletach?

222

W mojej aplikacji internetowej muszę wysyłać wiadomości e-mail do określonych użytkowników, takich jak [email protected], więc chcę dodać to do .propertiespliku i uzyskać do niego dostęp w razie potrzeby. Czy to poprawna procedura, jeśli tak, to gdzie powinienem umieścić ten plik? Korzystam z Netbeans IDE, które ma dwa osobne foldery na pliki źródłowe i JSP.

sansknwoledge
źródło
JNDI może być rozwiązaniem?
Basil Bourque

Odpowiedzi:

464

To Twój wybór. Istnieją zasadniczo trzy sposoby w archiwum aplikacji Java (WAR):


1. Umieść go w ścieżce klas

Abyś mógł załadować go ClassLoader#getResourceAsStream()ścieżką względną do ścieżki klas:

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

Tu foo.propertiesma być umieszczony w jednym z korzeni, które są objęte domyślnej ścieżki klasy webapp, np webapp użytkownika /WEB-INF/libi /WEB-INF/classes, serwera /liblub JDK / JRE użytkownika /lib. Jeśli plik właściwości jest specyficzny dla aplikacji internetowej, najlepiej jest go umieścić /WEB-INF/classes. Jeśli opracowujesz standardowy projekt WAR w IDE, upuść go w srcfolderze (folder źródłowy projektu). Jeśli korzystasz z projektu Maven, upuść go w /main/resourcesfolderze.

Możesz również umieścić go gdzieś poza domyślną ścieżką klasy i dodać jej ścieżkę do ścieżki klasy apserver. Na przykład w Tomcat możesz go skonfigurować jako shared.loaderwłaściwość Tomcat/conf/catalina.properties.

Jeśli umieściłeś foo.propertiesgo w podobnej strukturze pakietu Java com.example, musisz go załadować jak poniżej

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

Zauważ, że ta ścieżka modułu ładującego klasy kontekstu nie powinna zaczynać się od /. Tylko wtedy, gdy używasz „względnego” modułu ładującego, takiego jak SomeClass.class.getClassLoader(), wtedy rzeczywiście musisz go uruchomić za pomocą /.

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

Widoczność pliku właściwości zależy jednak od danego modułu ładującego klasy. Jest widoczny tylko dla tego samego modułu ładującego klasę, który załadował klasę. Jeśli więc klasa jest ładowana przez np. Wspólny moduł ładujący klasy serwera zamiast modułu ładującego klasy aplikacji sieci Web, a plik właściwości znajduje się w samej aplikacji sieci web, wówczas jest niewidoczny. Moduł ładujący klasy kontekstu jest najbezpieczniejszym wyborem, więc możesz umieścić plik właściwości „wszędzie” w ścieżce klasy i / lub zamierzasz mieć możliwość zastąpienia pliku dostarczonego przez serwer z aplikacji internetowej.


2. Umieść w treści WWW

Aby można go było załadować za ServletContext#getResourceAsStream()pomocą ścieżki względnej dla treści WWW:

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

Zauważ, że zademonstrowałem, aby umieścić plik w /WEB-INFfolderze, w przeciwnym razie byłby publicznie dostępny dla każdego przeglądarki. Zauważ też, że ServletContextjest w dowolnej HttpServletklasie, dostępny tylko dla dziedziczonych GenericServlet#getServletContext()i Filterprzez FilterConfig#getServletContext(). W przypadku, gdy nie jesteś w klasie serwletów, zwykle można to zrobić przez wstrzyknięcie @Inject.


3. Umieść go w lokalnym systemie plików dysku

Abyś mógł załadować go w zwykły java.iosposób z absolutną ścieżką lokalnego systemu plików na dysku:

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

Zwróć uwagę na znaczenie korzystania ze ścieżki bezwzględnej. Względne ścieżki lokalnego systemu plików dysku są absolutnie nie do przyjęcia w aplikacji internetowej Java EE. Zobacz także pierwszy link „Zobacz także” poniżej.


Który wybrać?

Po prostu rozważ zalety / wady według własnego uznania w zakresie konserwacji.

Jeśli pliki właściwości są „statyczne” i nigdy nie muszą się zmieniać w czasie działania, możesz zatrzymać je w WAR.

Jeśli wolisz móc edytować pliki właściwości spoza aplikacji internetowej bez potrzeby przebudowywania i ponownego wdrażania WAR za każdym razem, umieść go w ścieżce klasy poza projektem (w razie potrzeby dodaj katalog do ścieżki klasy).

Jeśli wolisz programowo edytować pliki właściwości z poziomu aplikacji internetowej za pomocą Properties#store()metody, umieść ją poza aplikacją internetową. Ponieważ Properties#store()wymaga to Writer, nie można poruszać się po ścieżce systemu plików dysku. Ścieżkę tę można z kolei przekazać do aplikacji sieci Web jako argument maszyny wirtualnej lub właściwość systemową. Ze względów bezpieczeństwa nigdy nie używajgetRealPath() . Wszystkie zmiany w folderze wdrażania zostaną utracone podczas ponownego wdrażania z tego prostego powodu, że zmiany nie są odzwierciedlone w oryginalnym pliku WAR.

Zobacz też:

BalusC
źródło
2
„Osobiście wolę umieszczać go w ścieżce klas poza projektem (dodaj nową ścieżkę do ścieżki klas)” zdezorientowany, czy możesz podać przykład?
Blankman
4
@Blankman Prawdopodobnie ma na myśli utworzenie nowego folderu, umieszczenie tam wszystkich niestandardowych plików konfiguracyjnych i dodanie tego folderu do ścieżki klasy. Więc: 1) Utwórz gdzieś folder o nazwie „appconfs” (może to być nawet /etc/appconfs2) Dodaj ten folder do ścieżki klas serwera aplikacji / domeny. Drugi krok jest specyficzny dla serwera aplikacji, nie sądzę, że istnieje na to ogólny przykład.
Tuukka Mustonen
Re: 2: Dlaczego oba "WEB-INF/filename.properties"i "/WEB-INF/filename.properties"(zauważ /na początku) działają? Czy jest jakiś powód, aby preferować jeden od drugiego?
Mr_and_Mrs_D
Naprawiono ten problem w ciągu ostatniego dnia. Nie mogę załadować mojego pliku właściwości. Jestem w stanie załadować go z dwóch miejsc. Jeden to katalog systemowy, a drugi to dysk lokalny. Działa z localhost. Ale chcę wdrożyć go na Amazon.
Arun Raja
Korzystam z IDE Netbeans i przechowuję plik właściwości na stronach internetowych / zasobach. Próbuję uzyskać do niego dostęp jako „./Web Pages / resources / config.properties”. Nie mam dostępu do tego. Proszę pomóż mi.
Arun Raja
9

Słowo ostrzeżenia: jeśli umieścisz pliki konfiguracyjne w swoim WEB-INF/classesfolderze, a twoje IDE, powiedzmy Eclipse, wykona czyszczenie / przebudowę, usunie twoje pliki conf, chyba że znajdują się one w katalogu źródłowym Java. Świetna odpowiedź BalusC nawiązuje do tego w opcji 1, ale chciałem podkreślić.

Nauczyłem się na własnej skórze, że „skopiowanie” projektu internetowego w Eclipse powoduje wyczyszczenie / przebudowanie z dowolnego folderu źródłowego. W moim przypadku dodałem „połączony WEB-INF/classeskatalog źródłowy” z naszej biblioteki Java POJO, kompilowałby się on do folderu. Wykonanie czyszczenia / przebudowy w tym projekcie (nie w projekcie aplikacji internetowej) spowodowało ten sam problem.

Pomyślałem o umieszczeniu moich confs w folderze src POJO, ale wszystkie te są przeznaczone dla bibliotek stron trzecich (takich jak Quartz lub URLRewrite), które znajdują się w WEB-INF/libfolderze, więc to nie miało sensu. Planuję przetestować umieszczenie go w folderze „src” projektów internetowych, gdy się do niego przejdę, ale ten folder jest obecnie pusty i pliki conf są w nim nieeleganckie.

Tak zagłosuję na oddanie pliki conf w WEB-INF/commonConfFolder/filename.properties, obok do folderu zajęć, który jest opcja Balus 2.

Ed Pike
źródło
1
jeśli umieścisz plik konfiguracyjny w podfolderze WEB_INF, to jak do niego dojdziesz? Nie miałem szczęścia z powiedzeniem „configFiles / prop.properties”
JesseBoyd
ok, to działa, umieszczając plik właściwości pod „Java Resources / src /”, nie działa z jednego z moich pakietów i musi znajdować się w katalogu głównym src. Twoje ostrzeżenie o nukowaniu folderu klas jest ważnym problemem.
JesseBoyd
6

Przykład: W pliku web.xml znacznik

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

I chat.properties możesz zadeklarować swoje właściwości w ten sposób

Na przykład:

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
źródło
5

Musi po prostu znajdować się w ścieżce klas (czyli upewnić się, że znajdzie się w katalogu / WEB-INF / klas w .war jako część kompilacji).

Taylor Leese
źródło
cześć dzięki za pomysł, ale mówi mi, że nie można znaleźć określonego pliku, tak, to jest problem ze ścieżką, jak podać ścieżkę
sansknwoledge
3

Możesz to zrobić z folderem źródłowym, więc przy każdej kompilacji pliki są automatycznie kopiowane do katalogu klas.

Zamiast używać pliku właściwości, użyj pliku XML.

Jeśli dane są zbyt małe, możesz nawet użyć pliku web.xml w celu uzyskania dostępu do właściwości.

Pamiętaj, że którekolwiek z tych podejść będzie wymagać ponownego uruchomienia serwera aplikacji, aby zmiany zostały odzwierciedlone.

Kalpak
źródło
umieściłem w folderze stron internetowych, ale nie mogę uzyskać do niego dostępu, nie znaleziono pliku nadchodzi błąd jak ustawić ścieżkę
sansknwoledge
1
jeśli twój plik znajdzie się w folderze WEB-INF / klas, jest on automatycznie ustawiany w ścieżce klasy
Kalpak
2

Załóżmy, że Twój kod szuka pliku, powiedz app.properties. Skopiuj ten plik do dowolnego katalogu i dodaj ten katalog do ścieżki klasy, tworząc plik setenv.sh w katalogu bin tomcat.

W pliku setenv.sh programu tomcat (jeśli ten plik nie istnieje, utwórz go, tomcat załaduje ten plik setenv.sh. #!/bin/sh CLASSPATH="$CLASSPATH:/home/user/config_my_prod/"

Nie powinieneś mieć swoich plików właściwości w ./webapps//WEB-INF/classes/app.properties

Moduł ładujący klasy Tomcat zastąpi ten z modułu WEB-INF / klas /

Dobra lektura: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html

Thar
źródło