Spring Boot 1.1.5 및 1.1.6 모두에서이 문제가 발생했습니다. STS (3.6.0, Windows) 내에서 애플리케이션을 실행할 때 잘 작동하는 @Value 주석을 사용하여 클래스 경로 리소스를로드하고 있습니다. 그러나 mvn 패키지를 실행 한 다음 jar를 실행하려고하면 FileNotFound 예외가 발생합니다.
리소스 message.txt는 src / main / resources에 있습니다. jar를 검사하고 최상위 수준 (application.properties와 동일한 수준)에 “message.txt”파일이 포함되어 있는지 확인했습니다.
응용 프로그램은 다음과 같습니다.
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application implements CommandLineRunner {
private static final Logger logger = Logger.getLogger(Application.class);
@Value("${message.file}")
private Resource messageResource;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... arg0) throws Exception {
// both of these work when running as Spring boot app from STS, but
// fail after mvn package, and then running as java -jar
testResource(new ClassPathResource("message.txt"));
testResource(this.messageResource);
}
private void testResource(Resource resource) {
try {
resource.getFile();
logger.debug("Found the resource " + resource.getFilename());
} catch (IOException ex) {
logger.error(ex.toString());
}
}
}
예외 :
c:\Users\glyoder\Documents\workspace-sts-3.5.1.RELEASE\classpath-resource-proble
m\target>java -jar demo-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.1.5.RELEASE)
2014-09-16 08:46:34.635 INFO 5976 --- [ main] demo.Application
: Starting Application on 8W59XV1 with PID 5976 (C:\Users\glyo
der\Documents\workspace-sts-3.5.1.RELEASE\classpath-resource-problem\target\demo
-0.0.1-SNAPSHOT.jar started by glyoder in c:\Users\glyoder\Documents\workspace-s
ts-3.5.1.RELEASE\classpath-resource-problem\target)
2014-09-16 08:46:34.640 DEBUG 5976 --- [ main] demo.Application
: Running with Spring Boot v1.1.5.RELEASE, Spring v4.0.6.RELEA
SE
2014-09-16 08:46:34.681 INFO 5976 --- [ main] s.c.a.AnnotationConfigA
pplicationContext : Refreshing org.springframework.context.annotation.Annotation
ConfigApplicationContext@1c77b086: startup date [Tue Sep 16 08:46:34 EDT 2014];
root of context hierarchy
2014-09-16 08:46:35.196 INFO 5976 --- [ main] o.s.j.e.a.AnnotationMBe
anExporter : Registering beans for JMX exposure on startup
2014-09-16 08:46:35.210 ERROR 5976 --- [ main] demo.Application
: java.io.FileNotFoundException: class path resource [message.
txt] cannot be resolved to absolute file path because it does not reside in the
file system: jar:file:/C:/Users/glyoder/Documents/workspace-sts-3.5.1.RELEASE/cl
asspath-resource-problem/target/demo-0.0.1-SNAPSHOT.jar!/message.txt
2014-09-16 08:46:35.211 ERROR 5976 --- [ main] demo.Application
: java.io.FileNotFoundException: class path resource [message.
txt] cannot be resolved to absolute file path because it does not reside in the
file system: jar:file:/C:/Users/glyoder/Documents/workspace-sts-3.5.1.RELEASE/cl
asspath-resource-problem/target/demo-0.0.1-SNAPSHOT.jar!/message.txt
2014-09-16 08:46:35.215 INFO 5976 --- [ main] demo.Application
: Started Application in 0.965 seconds (JVM running for 1.435)
2014-09-16 08:46:35.217 INFO 5976 --- [ Thread-2] s.c.a.AnnotationConfigA
pplicationContext : Closing org.springframework.context.annotation.AnnotationCon
figApplicationContext@1c77b086: startup date [Tue Sep 16 08:46:34 EDT 2014]; roo
t of context hierarchy
2014-09-16 08:46:35.218 INFO 5976 --- [ Thread-2] o.s.j.e.a.AnnotationMBe
anExporter : Unregistering JMX-exposed beans on shutdown
답변
resource.getFile()
리소스 자체가 파일 시스템에서 사용 가능할 것으로 예상합니다. 즉, jar 파일 내에 중첩 될 수 없습니다. 이것이 STS에서 애플리케이션을 실행할 때 작동하지만 애플리케이션을 빌드하고 실행 가능한 jar에서 실행하면 작동하지 않는 이유입니다. 오히려 사용하는 것보다 getFile()
자원의 내용에 액세스하려면, 내가 사용하는 것이 좋습니다 것 getInputStream()
대신. 그러면 리소스의 위치에 관계없이 리소스의 콘텐츠를 읽을 수 있습니다.
답변
당신은 스프링 프레임 워크를 사용하는 경우 다음 읽기 ClassPathResource
로하는 String
사용하여 아주 간단 스프링 프레임 워크의를FileCopyUtils
:
String data = "";
ClassPathResource cpr = new ClassPathResource("static/file.txt");
try {
byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
data = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
LOG.warn("IOException", e);
}
답변
파일을 사용하려는 경우 :
ClassPathResource classPathResource = new ClassPathResource("static/something.txt");
InputStream inputStream = classPathResource.getInputStream();
File somethingFile = File.createTempFile("test", ".txt");
try {
FileUtils.copyInputStreamToFile(inputStream, somethingFile);
} finally {
IOUtils.closeQuietly(inputStream);
}
답변
스프링 부트 프로젝트가 항아리로 실행되고 클래스 경로에서 일부 파일을 읽어야 할 때 아래 코드로 구현합니다.
Resource resource = new ClassPathResource("data.sql");
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
reader.lines().forEach(System.out::println);
답변
클래스 경로에서 파일을 쉽게 읽을 수 있도록 Java 8 방식으로 ClassPathResourceReader 클래스를 만들었습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import org.springframework.core.io.ClassPathResource;
public final class ClassPathResourceReader {
private final String path;
private String content;
public ClassPathResourceReader(String path) {
this.path = path;
}
public String getContent() {
if (content == null) {
try {
ClassPathResource resource = new ClassPathResource(path);
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
content = reader.lines().collect(Collectors.joining("\n"));
reader.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
return content;
}
}
이용:
String content = new ClassPathResourceReader("data.sql").getContent();
답변
나도이 제한에 직면했고 문제를 극복하기 위해이 라이브러리를 만들었습니다. spring-boot-jar-resources
기본적으로 필요에 따라 JAR에서 클래스 경로 리소스를 투명하게 추출하는 Spring Boot에 사용자 지정 ResourceLoader를 등록 할 수 있습니다.
답변
to get list of data from src/main/resources/data folder --
first of all mention your folder location in properties file as -
resourceLoader.file.location=data
inside class declare your location.
@Value("${resourceLoader.file.location}")
@Setter
private String location;
private final ResourceLoader resourceLoader;
public void readallfilesfromresources() {
Resource[] resources;
try {
resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:" + location + "/*.json");
for (int i = 0; i < resources.length; i++) {
try {
InputStream is = resources[i].getInputStream();
byte[] encoded = IOUtils.toByteArray(is);
String content = new String(encoded, Charset.forName("UTF-8"));
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
