Где разместить и как прочитать файлы ресурсов конфигурации в приложении на основе сервлетов?
В моем веб-приложении я должен отправить электронное письмо заранее определенным пользователям, таким как finance@xyz.com
так что я хочу добавить это к .properties
файл и доступ к нему при необходимости. Это правильная процедура, если да, то где мне разместить этот файл? Я использую среду IDE NetBeans, в которой есть две отдельные папки для исходных файлов и файлов JSP.
6 ответов
Это твой выбор. В архиве веб-приложений Java (WAR) есть три основных способа:
1. Поместите это в classpath
Так что вы можете загрузить его ClassLoader#getResourceAsStream()
с относительным путем к классу пути:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);
Вот foo.properties
предполагается поместить в один из корней, которые покрыты по умолчанию classpath веб-приложения, например, веб-приложения /WEB-INF/lib
а также /WEB-INF/classes
сервер /lib
или JDK/JRE /lib
, Если файл свойств зависит от веб-приложения, лучше всего поместить его в /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");
// ...
Однако видимость файла свойств зависит от загрузчика классов. Он виден только тому загрузчику классов, который загрузил класс. Таким образом, если класс загружается, например, общим загрузчиком классов сервера вместо загрузчика классов веб-приложения, и файл свойств находится внутри самого веб-приложения, то он невидим. Загрузчик классов контекста - ваша самая безопасная ставка, поэтому вы можете поместить файл свойств "повсюду" в путь к классам, и / или вы намерены иметь возможность переопределить файл, предоставленный сервером, из веб-приложения.
2. Поместите это в веб-контент
Так что вы можете загрузить его ServletContext#getResourceAsStream()
с относительным к веб-пути путем:
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
, вы не можете использовать путь к файловой системе диска. Этот путь в свою очередь может быть передан веб-приложению в качестве аргумента виртуальной машины или системного свойства. В качестве меры предосторожности никогда не используйте getRealPath()
, Все изменения в папке развертывания будут потеряны при повторном развертывании по той простой причине, что изменения не отражаются обратно в исходном файле WAR.
Смотрите также:
Слово предупреждения: если вы положите файлы конфигурации в свой 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 в ней кажутся не элегантными.
Так что я голосую за размещение конф файлов в WEB-INF/commonConfFolder/filename.properties
, рядом с папкой классов, которая является вариантом 2 Balus.
Пример: в файле 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 вы можете объявить свои свойства, как это
Например:
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.
Он просто должен быть в пути к классам (он также должен быть в каталоге /WEB-INF/classes в.war как часть сборки).
Вы можете использовать свою исходную папку, чтобы при сборке эти файлы автоматически копировались в каталог классов.
Вместо использования файла свойств используйте файл XML.
Если данные слишком малы, вы даже можете использовать web.xml для доступа к свойствам.
Обратите внимание, что любой из этих подходов потребует перезапуска сервера приложений, чтобы изменения были отражены.
Предположим, ваш код ищет файл, скажем, app.properties. Скопируйте этот файл в любой каталог и добавьте этот каталог в classpath, создав файл setenv.sh в каталоге bin tomcat.
В вашем setenv.sh tomcat (если этот файл не существует, создайте его, tomcat загрузит этот файл setenv.sh).
#!/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