Где разместить и как читать файлы ресурсов конфигурации в приложении на основе сервлета?

В моем веб-приложении мне нужно отправить электронное письмо на набор предопределенных пользователей, таких как [email protected], поэтому я хочу добавить это в файл .properties и получить доступ к нему по мере необходимости. Это правильная процедура, если да, то где я должен разместить этот файл? Я использую Netbeans IDE, который имеет две отдельные папки для исходных и JSP файлов.

Ответ 1

Это ваш выбор. В основном архиве веб-приложений Java (WAR) есть три способа:


1. Поместите его в classpath

Чтобы вы могли загрузить его ClassLoader#getResourceAsStream() с относительным путем classpath:

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

Здесь foo.properties предполагается разместить в одном из корней, которые покрываются путём по умолчанию для webapp, например. webapp /WEB-INF/lib и /WEB-INF/classes, сервер /lib или JDK/JRE /lib. Если файл свойств специфичен для webapp, лучше всего поместить его в /WEB-INF/classes. Если вы разрабатываете стандартный проект WAR в среде IDE, поместите его в папку src (исходная папка проекта). Если вы используете проект Maven, поместите его в папку /main/resources.

Вы также можете поместить его куда-то за пределы пути по умолчанию и добавить его путь к пути к классам на сервере приложений. Например, в Tomcat вы можете настроить его как shared.loader свойство Tomcat/conf/catalina.properties.

Если вы разместили foo.properties его в структуре пакета Java, например com.example, вам необходимо загрузить его ниже

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

Обратите внимание, что этот путь загрузчика класса контекста не должен начинаться с /. Только когда вы используете "относительный" загрузчик классов, например SomeClass.class.getClassLoader(), вам действительно нужно запустить его с помощью /.

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

Однако видимость файла свойств зависит от того, какой класс загрузчика класса находится под вопросом. Он доступен только для того же загрузчика классов, что и тот, который загружал класс. Таким образом, если класс загружается, например, server common classloader вместо загрузчика классов webapp, а файл свойств находится внутри самого webapp, а затем он невидим. Загрузчик класса контекста - это ваша самая безопасная ставка, поэтому вы можете поместить файл свойств "всюду" в путь к классам и/или вы намереваетесь переопределить предоставленный сервером один из веб-сервера.


2. Поместите его в webcontent

Чтобы вы могли загрузить его ServletContext#getResourceAsStream() с относительным путем webcontent:

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

Обратите внимание, что я продемонстрировал размещение файла в папке /WEB-INF, иначе он был бы общедоступным для любого веб-браузера. Также обратите внимание, что ServletContext находится в любом классе HttpServlet, доступном только для унаследованного GenericServlet#getServletContext() и Filter FilterConfig#getServletContext(). Если вы не находитесь в классе сервлета, он обычно просто вводится через @Inject.


3. Поместите его в локальную файловую систему диска

Чтобы вы могли загрузить обычный java.io путь с полным пути к файловой системе локального диска:

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

Обратите внимание на важность использования абсолютного пути. Относительные пути локальной файловой системы на диске - это абсолютное отсутствие в веб-приложении Java EE. См. Также первую ссылку "См. Также" ниже.


Что выбрать?

Просто взвешивайте преимущества/недостатки в своем собственном мнении о ремонтопригодности.

Если файлы свойств "статические" и никогда не должны меняться во время выполнения, вы можете сохранить их в WAR.

Если вы предпочитаете редактировать файлы свойств вне веб-приложения без необходимости пересортировки и повторного развертывания WAR каждый раз, тогда поместите его в путь класса вне проекта (при необходимости добавьте каталог в путь к классам).

Если вы предпочитаете редактировать файлы свойств программным способом из веб-приложения с помощью метода Properties#store(), выведите его за пределы веб-приложения. Поскольку для Properties#store() требуется Writer, вы не можете использовать путь к файловой системе диска. Этот путь, в свою очередь, может быть передан в веб-приложение как аргумент VM или системное свойство. В качестве меры предосторожности никогда используйте getRealPath(). Все изменения в папке развертывания будут потеряны при повторном развертывании по той простой причине, что изменения не будут отражены в исходном файле WAR.

См. также:

Ответ 2

Слово предупреждения: если вы поместите файлы конфигурации в папку WEB-INF/classes, и ваша IDE, скажем, Eclipse, выполнит очистку/перестройку, она уничтожит ваши файлы conf, если они не были в исходном каталоге Java. Отличный ответ BalusC намекает на это в варианте 1, но я хотел добавить акцент.

Я усвоил трудный путь, что если вы "копируете" веб-проект в Eclipse, он выполняет очистку/перестройку из любых исходных папок. В моем случае я добавил "dir связанный источник" из нашей библиотеки Java POJO, он будет компилироваться в папку WEB-INF/classes. Выполнение очистки/перестройки в этом проекте (не в проекте веб-приложения) вызвало ту же проблему.

Я думал о том, чтобы поместить свои файлы в папку POJO src, но все эти файлы предназначены для сторонних библиотек (таких как Quartz или URLRewrite), которые находятся в папке WEB-INF/lib, так что это не имело смысла. Я планирую проверить, поместив его в папку "src" веб-проектов, когда доберусь до него, но в данный момент эта папка пуста, и в ней содержатся файлы conf, которые кажутся не элегантными.

Поэтому я голосую за размещение файлов conf в файле WEB-INF/commonConfFolder/filename.properties рядом с папкой классов, которая является вариантом 2 Balus.

Ответ 3

Пример: в файле web.xml тег

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

И chat.properties вы можете объявить свои свойства следующим образом

Для 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.

Ответ 4

Он просто должен быть в пути к классам (также убедитесь, что он попадает под /WEB -INF/classes в .war как часть сборки).

Ответ 5

Вы можете использовать свою исходную папку, чтобы при сборке эти файлы автоматически копировались в каталог классов.

Вместо использования файла свойств используйте файл XML.

Если данные слишком малы, вы даже можете использовать web.xml для доступа к свойствам.

Обратите внимание, что любой из этих подходов потребует перезапуска сервера приложений, чтобы изменения были отражены.

Ответ 6

Предположим, ваш код ищет файл, скажем, app.properties. Скопируйте этот файл в любой каталог и добавьте этот каталог в classpath, создав файл setenv.sh в каталоге bin tomcat.

В вашем setenv.sh tomcat (если этот файл не существует, создайте его, tomcat загрузит этот файл setenv.sh. #!/bin/sh CLASSPATH="$CLASSPATH: /home/user/config_my_prod/" Bin #!/bin/sh CLASSPATH="$CLASSPATH: /home/user/config_my_prod/"

Вы не должны иметь свои файлы свойств в. /webapps//WEB-INF/classes/app.properties

Загрузчик классов Tomcat переопределит тот из WEB-INF/classes/

Хорошее чтение: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html