반응형
Spring boot는 내장 톰캣이 있기 때문에 jar배포를 하면 내부적으로 톰캣을 띄울 수 있습니다. 그런데 배포하자마자 resource에서 excel file 읽어올 때 에러가 났습니다. fileNotfound!!!
문제되는 소스는 아래와 같습니다.
File file = ResourceUtils.getFile("classpath:" + filePath);
Local에서는 정상작동하는데 왜 안되는가 하고 여러가지 시도를 했습니다.
URL은 잘 가져오나?
URL url = ResourceUtils.getURL("classpath:"+filePath);
결과는
url=jar:file:/home/yongtae/server/test-project-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/excel/
잘 가져온다! 근데 경로가 이상하다.
경로때문에 문제가 있는건가? "jar: file: !" 지워보자
소스 수정하고 다시 도전해보자
String url = url.replace("jar:", "").replace.("file:", "").replace("!");
File file = ResourceUtils.getFile("classpath:" + filePath);
결과는 똑같이 fileNotFound..
더 구글링을 해보니 jar로 배포하면 jar 내부에 있는 file에 접근하려면 getFile으로는 불가능하다고 합니다.
결국 직장동료의 도움을 받아 ClassPathResource클래스를 쓰면 된다고 합니다.
해결
아래 소스로 하면 에러없이 작동합니다!
ClassPathResource classPathResource = new ClassPathResource(filePath);
if(classPathResource.exists() == false){
log.error("Invalid filePath : {}", filePath);
throw new IllegalArgumentException();
}
log.info("file path exists = {}", classPathResource.exists());
try (InputStream is = new BufferedInputStream(classPathResource.getInputStream())) {
// logic...
}
ClassPathResource 내부 소스를 보니 클래스 생성 시 path와 classLoader를 생성합니다.
public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
Assert.notNull(path, "Path must not be null");
String pathToUse = StringUtils.cleanPath(path);
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
this.path = pathToUse;
this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}
file을 stream 형식으로 읽어옵니다.
@Override
public InputStream getInputStream() throws IOException {
InputStream is;
if (this.clazz != null) {
is = this.clazz.getResourceAsStream(this.path);
}
else if (this.classLoader != null) {
is = this.classLoader.getResourceAsStream(this.path);
}
else {
is = ClassLoader.getSystemResourceAsStream(this.path);
}
if (is == null) {
throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
}
return is;
}
결론
결론적으로 jar 배포를 하면 jar 안의 file에 접근하려면 Stream을 사용해야합니다
반응형