Java:在Spring Boot中从类路径加载文件

资源加载器

使用Java,您可以使用当前线程的classLoader并尝试加载文件,但是Spring Framework为您提供了更为优雅的解决方案,例如ResourceLoader。

您只需要自动连接ResourceLoader,然后调用getResource(“somePath”)方法即可。

在Spring Boot(WAR)中从资源目录/类路径加载文件的示例

在下面的示例中,我们从类路径中加载名为GeoLite2-Country.mmdb的文件作为资源,然后将其作为File对象检索。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@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.");
}
}
}
}

从Spring Boot JAR加载文件

如果您想从Spring Boot JAR中的 classpath加载文件,则必须使用该resource.getInputStream()方法将其作为InputStream检索。如果尝试使用resource.getFile()该方法,则会收到错误消息,因为Spring尝试访问文件系统路径,但无法访问JAR中的路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@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.");
}
}
}
}