jar로 실행할 때 클래스 경로 리소스를 찾을 수 없음
Spring Boot 1.1.5와 1.1.6 모두에서 이 문제가 발생 - @Value 주석을 사용하여 클래스 경로 리소스를 로드하고 있습니다.STS(3.6.0, Windows) 내에서 애플리케이션을 실행하면 정상적으로 작동합니다.그러나 mvn 패키지를 실행하고 jar를 실행하려고 하면 FileNotFound 예외가 나타납니다.
자원, 메시지txt는 src/main/src입니다.항아리를 검사해 보니 "메시지" 파일이 들어 있더군요txt"를 선택합니다(application.properties와 같은 수준).
응용 프로그램은 다음과 같습니다.
@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(Spring Tool Suite)에서 응용 프로그램을 실행할 때는 작동하지만 응용 프로그램을 빌드하고 실행 가능한 jar에서 실행한 후에는 작동하지 않습니다.사용하는 대신getFile()
리소스 콘텐츠에 액세스하려면 를 사용하는 것이 좋습니다.그러면 위치에 관계없이 리소스의 내용을 읽을 수 있습니다.
Spring을 .ClassPathResource
String
Spring Framework를 사용하면 매우 간단합니다.
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);
}
spring boot project가 jar로 실행되어 classpath의 파일을 읽을 필요가 있을 때, 나는 그것을 아래 코드로 구현한다.
Resource resource = new ClassPathResource("data.sql");
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
reader.lines().forEach(System.out::println);
ClassPathResourceReader 클래스를 Java 8 방식으로 생성하여 classpath에서 파일을 쉽게 읽을 수 있도록 했습니다.
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();
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);
}
}
이 제한에 직면하여 이 라이브러리를 작성하여 문제를 해결했습니다.spring-boot-jar-resources 기본적으로는 필요에 따라 JAR에서 클래스 경로 리소스를 추출하는 Spring Boot에 커스텀 ResourceLoader를 등록할 수 있습니다.
저지는 포장을 풀어야 해
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<requiresUnpack>
<dependency>
<groupId>com.myapp</groupId>
<artifactId>rest-api</artifactId>
</dependency>
</requiresUnpack>
</configuration>
</plugin>
</plugins>
</build>
또 다른 중요한 점은 응용 프로그램을 실행할 때 리소스 폴더의 파일/폴더에 있는 대문자를 무시하지 않고 jar로 실행한다는 것입니다.이 [Resources]의 [더에 있는 경우Testfolder/messages.txt
@Autowired
ApplicationContext appContext;
// this will work when running the application, but will fail when running as jar
appContext.getResource("classpath:testfolder/message.txt");
따라서 ClassPath Resource의 컨스트럭터에 대문자 또는 대문자 추가는 하지 마십시오.
appContext.getResource("classpath:Testfolder/message.txt");
솔루션은 인정된 답변에 따라 정확합니다.임시 파일을 만들고 텍스트를 읽는 대신 Stream Utils를 사용하여 Stream to String을 보다 효율적으로 읽을 수 있는 솔루션을 제공하고 있습니다.
@Bean
public String readFromResource(final @Value("classpath:data/message.txt") Resource messageFile)
throws IOException {
return StreamUtils.copyToString(messageFile.getInputStream(), StandardCharsets.UTF_8);
}
in spring boot :
1) if your file is ouside jar you can use :
@Autowired
private ResourceLoader resourceLoader;
**.resource(resourceLoader.getResource("file:/path_to_your_file"))**
2) if your file is inside resources of jar you can `enter code here`use :
**.resource(new ClassPathResource("file_name"))**
Andy의 답변에 따라 다음 명령을 사용하여 리소스 내의 디렉토리 및 하위 디렉토리 아래에 있는 모든 YAML의 입력 스트림을 가져옵니다(통과된 경로는 다음 문자로 시작하지 않음)./
private static Stream<InputStream> getInputStreamsFromClasspath(
String path,
PathMatchingResourcePatternResolver resolver
) {
try {
return Arrays.stream(resolver.getResources("/" + path + "/**/*.yaml"))
.filter(Resource::exists)
.map(resource -> {
try {
return resource.getInputStream();
} catch (IOException e) {
return null;
}
})
.filter(Objects::nonNull);
} catch (IOException e) {
logger.error("Failed to get definitions from directory {}", path, e);
return Stream.of();
}
}
원래 오류 메시지에 대해서
파일 시스템에 존재하지 않기 때문에 절대 파일 경로로 확인할 수 없습니다.
경로 문제의 해결책을 찾는 데 도움이 될 수 있는 코드는 다음과 같습니다.
Paths.get("message.txt").toAbsolutePath().toString();
이것에 의해, 애플리케이션이 어디에서 파일을 찾을지 판단할 수 있습니다.이것은 어플리케이션의 메인 방법으로 실행할 수 있습니다.
나는 같은 오류에 직면해 있었다.
InputStream inputStream = 새 ClassPathResource("filename.ext").inputStream();
실행 중 FileNotFoundException이 해결됩니다.
정적인 맥락에서 효과가 있었습니다.
InputStream inputStream = ClassName.class.getClassLoader().getResourceAsStream("folderName/fileName.xml");
Reader reader = new InputStreamReader(inputStream);
String xml = CharStreams.toString(reader);
"java - jar < file_name.jar"를 실행하는 동안 동일한 문제가 발생했습니다.STS에서 실행했을 때는 정상적으로 동작하고 있었습니다.다음 행은 문자열 templateFilePath = "/templates/Itemized_Report_2021_V1.xlsx" 문제를 해결하는 데 도움이 되었습니다. InputStream resourceFile = **getClass().getResourceAsStream(templateFilePath)
Excel 보고서 파일템플릿 경로./templates/Itemized_Report_2021_V1.xlsx java.io 。FileNotFoundException: D:\STS%20WORKspace\app\target\classes\템플릿\Itemized_Report_2021_V1.xlsx(지정된 경로를 찾을 수 없습니다)
해결 방법: @Override public void exportExcelReport(HttpServletResponse 응답, List contexts)가 IOException, URISyntaxException { String templateFilePath = "/templates/Itemized_2021_V1.xlsxls"; InputStreamResource get(get)을 실행합니다.xlset(get).예외("템플릿 파일을 찾을 수 없습니다!" + templateFilePath), } other {ServletOutputStream outputStream = null. {log.info comb Companency Excel 보고서 파일 템플릿 경로 {}), templateFilePath.워크북 = 새로운 XSSFWorkbook(resourceFile), prepareCompetencyReport(콘텍스트), prepareItemizedReport(콘텍스트);
// Return as octet-stream format in the rest response
outputStream = response.getOutputStream();
workbook.write(outputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
workbook.close();
if (outputStream != null)
outputStream.close();
}
}
}
언급URL : https://stackoverflow.com/questions/25869428/classpath-resource-not-found-when-running-as-jar
'programing' 카테고리의 다른 글
돌연변이에 대한 Vuex 도우미 메서드 (0) | 2022.08.28 |
---|---|
classpath 디렉토리에서 리소스 목록을 가져옵니다. (0) | 2022.08.28 |
상태가 업데이트될 때 구성 요소가 다시 렌더링되지 않음 (0) | 2022.08.28 |
"../include/header"와 같은 상대 경로의 이점은 무엇입니까?h"는 헤더에 사용할 수 있습니까? (0) | 2022.08.28 |
SIGSEGV를 잡기 위한 신호 핸들러 작성 방법 (0) | 2022.08.27 |