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);
(обратите внимание, что этот путь не может начинаться с /
, он всегда относительно общего корня)
Смотри также: