天天看點

SpringBoot 系列-資源通路

當我們建立一個 SpringBoot web 應用時,有時候需要從 classpath 去加載一些檔案,這裡記錄下在 war 和 jar 兩種不同檔案格式下加載檔案的解決方案。

The ResourceLoader

在 Java 中 ,我們可以使用目前線程的 classLoader 去嘗試加載檔案,但是 Spring Framework 為我們提供了更加優雅的解決方案,例如 ResourceLoader。

使用 ResourceLoader 時,我們隻需要使用 @Autowire 自動注入 ResourceLoader,然後調用 getResource(“somePath”) 方法即可。

在Spring Boot(WAR)中從資源目錄/類路徑加載檔案的示例

@Service("geolocationservice")
public class GeoLocationServiceImpl implements GeoLocationService {
    private static final Logger LOGGER = LoggerFactory.getLogger(GeoLocationServiceImpl.class);
    private static DatabaseReader reader = null;
    private ResourceLoader resourceLoader;
    @Autowired
    public GeoLocationServiceImpl(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @PostConstruct
    public void init() {
        try {
            LOGGER.info("GeoLocationServiceImpl: Trying to load GeoLite2-Country database...");
            Resource resource = resourceLoader.getResource("classpath:GeoLite2-Country.mmdb");
            File dbAsFile = resource.getFile();
            // Initialize the reader
            reader = new DatabaseReader
                        .Builder(dbAsFile)
                        .fileMode(Reader.FileMode.MEMORY)
                        .build();
            LOGGER.info("GeoLocationServiceImpl: Database was loaded successfully.");
        } catch (IOException | NullPointerException e) {
            LOGGER.error("Database reader cound not be initialized. ", e);
        }
    }
    @PreDestroy
    public void preDestroy() {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                LOGGER.error("Failed to close the reader.");
            }
        }
    }
}           

複制

從 SpringBoot FatJar 中加載資源

如果我們想從 Spring Boot JAR 中的類路徑加載檔案,則必須使用 resource.getInputStream() 方法将其作為 InputStream 檢索。如果嘗試使用resource.getFile(),則會收到錯誤消息,因為 Spring 嘗試通路檔案系統路徑,但它無法通路 JAR 中的路徑。

@Service("geolocationservice")
public class GeoLocationServiceImpl implements GeoLocationService {
    private static final Logger LOGGER = LoggerFactory.getLogger(GeoLocationServiceImpl.class);
    private static DatabaseReader reader = null;
    private ResourceLoader resourceLoader;

    @Inject
    public GeoLocationServiceImpl(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @PostConstruct
    public void init() {
        try {
            LOGGER.info("GeoLocationServiceImpl: Trying to load GeoLite2-Country database...");
            Resource resource = resourceLoader.getResource("classpath:GeoLite2-Country.mmdb");
            InputStream dbAsStream = resource.getInputStream(); // <-- this is the difference
            // Initialize the reader
            reader = new DatabaseReader
                        .Builder(dbAsStream)
                        .fileMode(Reader.FileMode.MEMORY)
                        .build();
            LOGGER.info("GeoLocationServiceImpl: Database was loaded successfully.");
        } catch (IOException | NullPointerException e) {
            LOGGER.error("Database reader cound not be initialized. ", e);
        }
    }

    @PreDestroy
    public void preDestroy() {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                LOGGER.error("Failed to close the reader.");
            }
        }
    }
}           

複制

▐ 文章來源: 磊叔授權分享,轉載請先聯系原作者,謝謝!