Программный доступ к файлу свойств в приложении JSF
Я пытаюсь получить доступ к файлу свойств i18n, который я использую в своем приложении JSF в коде. (Идея состоит в том, чтобы иметь страницу, которая отображает свои ключи и значения в виде таблицы.)
Это проект maven, находящийся в папке src / resources / localization и развернутый в файле war в WEB-INF\classes\localization\
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
Но переменная foo оказывается нулевой, независимо от того, какую переменную пути я установил, /WEB-INF/classes/localization/stat_codes.properties, "localization.stat_codes.properties" и т. Д. Подобный вопрос здесь, но полезного нет Ответь и там.
2 ответа
Class#getResourceAsStream()
может взять путь, который относительно расположения Class
который вы используете там в качестве отправной точки. Так, например, если класс находится в com.example
пакет и вы просите путь foo/filename.properties
то он действительно загрузит com/example/foo/filename.properties
файл. Но если вы используете /foo/filename.properties
, то это будет на самом деле загрузить foo/filename.properties
из корня пути к классам.
Итак, ваш код
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);
на самом деле будет искать java/util/localization/stat_codes.properties
файл.
Но в приложениях со сложной иерархией загрузчиков классов один загрузчик классов не является другим. Загрузчик классов, который загрузил основные классы Java, не обязательно знает о файлах, которые находятся в веб-приложении. /WEB-INF/classes
, Таким образом, префикс пути с /
не обязательно будет решением, оно все равно вернется null
,
Если вы можете гарантировать, что текущий класс видим тем же загрузчиком классов, что и файлы свойств (потому что они находятся в том же подкорне пути к классам, например /WEB-INF/classes
тогда вы действительно должны использовать
String path = "/localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);
Но если в какой-то момент файлы свойств будут выведены из-за более простого обслуживания / редактирования во время выполнения, так что вам не нужно перестраивать / повторно развертывать / перезапускать веб-приложение всякий раз, когда вы хотите отредактировать файлы, тогда приведенная выше строка кода скорее всего потерпит неудачу. Внешнее местоположение будет доступно только другому загрузчику классов. Каноническое решение состоит в том, чтобы использовать загрузчик классов контекста потока в качестве отправной точки, он имеет доступ ко всем ресурсам в пути к классам.
String path = "localization/stat_codes.properties";
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream foo = loader.getResourceAsStream(path);
(обратите внимание, что этот путь не может начинаться с /
всегда относительно общего корня)
Смотрите также:
Похоже, виновником является prop
объект, я предположил, что любой объект будет работать, но это должен быть текущий объект (this
) по которому метод getClass()
кажется, вызывается Кроме того, путь должен начинаться с /
так как localization
каталог находится в WEB-INF/classes
,
String path = "localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);