當我們建立一個 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.");
}
}
}
}
複制
▐ 文章來源: 磊叔授權分享,轉載請先聯系原作者,謝謝!