Maven использует так называемый стандартный макет каталога а>. Если вы не будете следовать этому макету, плагины не смогут правильно выполнять свою работу. Технически вы можете настроить Maven для использования разных каталогов, но в 99,999% случаев в этом нет необходимости.
Одной из особенностей этого макета является то, что производственные файлы помещаются в:
<project-dir>/src/main/java
<project-dir>/src/main/resources
- All non-
*.java
files (that are meant to be resources)
Когда вы создаете свой проект, исходные файлы Java компилируются, а файлы *.class
помещаются в каталог target/classes
; это делается maven-compiler-plugin
. При этом файлы ресурсов копируются из src/main/resources
в target/classes
; maven-resources-plugin
отвечает за это.
Примечание. См. Введение. в Жизненный цикл сборки для получения дополнительной информации о фазах и о том, какие подключаемые модули на какой фазе выполняются. Этот вопрос о переполнении стека также может быть полезным.
Когда вы запускаете приложение из IDE (возможно, через exec-maven-plugin
), каталог target/classes
помещается в путь к классам. Это означает, что все скомпилированные классы из src/main/java
и все скопированные ресурсы из src/main/resources
доступны для использования через путь к классам.
Затем, когда вы упаковываете свое приложение в файл JAR, все файлы в target/classes
добавляются в результирующий файл JAR (обрабатывается maven-jar-plugin
). Сюда входят ресурсы, скопированные с src/main/resources
. Когда вы запускаете приложение с использованием этого файла JAR, ресурсы по-прежнему доступны для использования через путь к классам, поскольку они встроены в файл JAR.
Чтобы сделать resource.txt
доступным в пути к классам, просто переместите:
<project-dir>/resource.txt
To:
<project-dir>/src/main/resources/resource.txt.
Затем вы можете использовать Class#getResource
с /resource.txt
в качестве пути, и все должно получиться у вас. URL
, возвращаемый getResource
, будет отличаться в зависимости от того, выполняете ли вы target/classes
или JAR-файл.
При выполнении против target/classes
вы получите что-то вроде:
file:///.../<project-dir>/target/classes/resource.txt
При выполнении против файла JAR вы получите что-то вроде:
jar:file:///.../<project-dir>/target/projectname-version.jar!/resource.txt
Примечание. Все это предполагает, что resource.txt
на самом деле должен быть ресурсом, а не внешним файлом. Ресурсы обычно доступны только для чтения после развертывания в файле JAR; если вам нужен файл с возможностью записи, вы можете использовать указанное место для файла (например, папку в домашнем каталоге пользователя). Обычно доступ к внешним файлам осуществляется через java.io.File
или java.nio.file.*
. Помните, что ресурсы — это не то же самое, что обычные файлы.
Теперь, если бы вы поместили resource.txt
непосредственно под <project-dir>
, это ничего не значило бы для Maven. Он не будет скопирован в target/classes
или окажется в файле JAR, что означает, что ресурс никогда не будет доступен в пути к классам. Итак, повторюсь: все ресурсы относятся к категории src/main/resources
.
Ознакомьтесь с Javadoc по адресу java.lang.Class#getResource(String)
для получения дополнительной информации о пути, например о том, когда следует использовать начальный /
, а когда нет. Ссылка указывает на Javadoc для Java 12, который включает информацию о ресурсах и модулях (модули JPMS/Jigsaw, а не модули Maven); если вы не используете модули, вы можете игнорировать эту часть документации.
26.06.2019
src/main/resources
:`BufferedReader br = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream("/resource.txt")));
. После запуска командыpackage
Maven все, что находится внутриsrc/main/resources
, копируется внутрьtarget/classes
. Вот откудаMain.java
из IDE берет файл. В то же время командаpackage
создает банку, которая берет файлы изtarget/classes
и помещает их в свой корень. 02.07.2019