Загрузка файлов из пути к классам и .jar

Я создаю веб-приложение Spring Boot, и мне нужно читать статические файлы (.json) при запуске.

Нет проблем, работает, когда я запускаю приложение в Idea. Но если я запускаю пакет mvn и запускаю банку, указанный путь (BASE_DIR) больше не существует, поэтому файлы не могут быть найдены.

Как я могу решить читать файлы, начинающиеся с Idea и .jar?

package skyxplore.dataaccess.gamedata.base;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import org.apache.commons.io.FilenameUtils;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import skyxplore.dataaccess.gamedata.entity.abstractentity.GeneralDescription;

@Slf4j
public abstract class AbstractGameDataService<V> extends HashMap<String, V> {
    public static final String BASE_DIR = "src/main/resources/data/gamedata/";

    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final JsonFileFilter jsonFilter = new JsonFileFilter();

    private final String source;

    public AbstractGameDataService(String source) {
        this.source = BASE_DIR + source;
    }

    protected void loadFiles(Class<V> clazz) {
        File root = new File(source);
        if (!root.exists()) {
            throw new IllegalStateException("Source directory does not exists. Path: " + root.getAbsolutePath());
        }
        if (!root.isDirectory()) {
            throw new IllegalArgumentException("Source must be a directory. Path: " + root.getAbsolutePath());
        }
        File[] files = root.listFiles(jsonFilter);
        for (File file : files) {
            try {
                String key = FilenameUtils.removeExtension(file.getName());
                V content = objectMapper.readValue(file, clazz);
                if (content instanceof GeneralDescription) {
                    GeneralDescription d = (GeneralDescription) content;
                    log.info("Loaded element. Key: {}, Value: {}", key, content);
                    put(d.getId(), content);
                } else {
                    throw new RuntimeException(source + " cannot be loaded. Unknown data type.");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public abstract void init();
}

person Saphyra    schedule 23.07.2018    source источник


Ответы (2)


После упаковки приложений файлы ресурсов больше не доступны из файловой системы, поэтому вы не можете перечислить / открыть их с помощью File. Вам нужно прочитать их как ресурсы из JAR, например, используя class.readResourceAsStream. Когда вы запускаете его из IntelliJ, файлы читаются не из JAR, а из каталога проекта.

Здесь у вас есть учебник Java Oracle по использованию ресурсов < / а>

Другое решение (поскольку у вас есть дополнительная логика для чтения файлов) вы можете отложить файлы в сторону JAR, а не как ресурс, и затем прочитать их оттуда.

person Antoniossss    schedule 23.07.2018
comment
class.getResourceAsStream возвращает поток одного указанного файла. Но мне нужно сканировать одну указанную папку и читать все файлы один за другим. - person Saphyra; 23.07.2018
comment
Я знаю, что эту проблему нужно преодолеть. Google о том, как перечислять ресурсы. - person Antoniossss; 23.07.2018

BASE_DIR = "src/main/resources/data/gamedata/"

После создания пакета mvn папка src/main/resources становится корнем jar-файла. Вы можете использовать загрузчик классов, чтобы загрузить этот файл. Что-то типа:

AbstractGameDataService.class.getResourceAsStream("/data/gamedata/<your json file>")

Другой вариант, поскольку вы используете Spring-boot, вы можете использовать само сканирование Spring. Используя пружинные конструкции, загрузите файл, используя: classpath:/data/gamedata/<your json file>

person Himanshu Bhardwaj    schedule 23.07.2018