В моем веб-приложении мне нужно отправить электронное письмо на набор предопределенных пользователей, таких как [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