Программный доступ к файлу свойств в приложении 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);
Другие вопросы по тегам