使用可执行Jar时找不到Spring-Boot资源

我再次遇到一个奇怪的问题,希望有人可以提供帮助。

我有一个spring boot后端模块,在eclipse中运行良好,在application.java中启动main时应用程序是可执行的。 一切都很好。

我的应用程序使用csv-files将示例数据导入数据库,这些文件包含在src / main / resources文件夹中。 如上所述,在eclipse中启动时一切正常。

现在我想将它作为可执行jar执行,应用程序开始启动然后无法启动,因为它无法找到csv文件。 它打印出来的路径,它查找文件的位置是正确的,csv文件包含在jar中。

该模块的Pom如下所示:

 4.0.0  at.company.bbsng bbsng-import 0.1.0-SNAPSHOT  bbsng-import-backend bbsng-import-backend  at.company.bbsng.dataimport.Application     org.springframework.boot spring-boot-starter-batch    spring-boot-starter-logging org.springframework.boot     org.springframework.boot spring-boot-starter-log4j   org.springframework.boot spring-boot-starter-test test   ...     org.springframework.boot spring-boot-maven-plugin    repackage        

csv文件的路径在propery文件中配置如下:

 # EXAMPLE PATH csv.path=config/csv/ 

java配置文件的部分如下:

  ... @Value("${csv.path}") private String csvExamplePath; @Bean public Resource addressResource() { return new ClassPathResource(csvExamplePath + CSV_ADDRESS); } ... 

在jar中,文件位于路径中

 \config\csv\ 

堆栈跟踪:

 Caused by: java.io.FileNotFoundException: class path resource [config/csv/Company.csv] cannot be resolved to absolute file path because it does not reside in th e file system: jar:file:/C:/Development/Projekte/bbsng/trunk/import/backend/target/bbsng-import-backend-0.1.0-SNAPSHOT.jar!/config/csv/Company.csv at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:207) at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52) at at.compax.bbsng.dataimport.app.source.company.CompanyGenerator.init(CompanyGenerator.java:28) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java 

同样,应用程序在从eclipse启动时按预期工作,只有可执行jar抱怨缺少csv文件,jar中已有的内容。

任何线索都会很棒。

好的,我已经找到了真正的问题和解决方案。

首先,应用程序使用正确的csv文件路径,但是在使用我在以下链接中找到的可执行jar时还有另一个问题。 计算器,链接

在我开始使用可执行jar之前,我使用以下解决方案来获取CSV文件(问题是getFile()):

 final List resourceLines = FileReadUtils.readLines(specialisationResource.getFile()); for (final String line : resourceLines) { data.add(getNewTransientSpecialisation(line)); } 

但是在可执行的jar中我无法将我的资源用作文件,我需要将其用作流,请参阅上面提供的链接。 所以我需要改变我的代码。 如果您更喜欢使用本机java,则可以执行以下操作:

 final InputStream inputStream = specialisationResource.getInputStream(); final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = bufferedReader.readLine()) != null) { data.add(getNewTransientSpecialisation(line)); } 

我更喜欢使用框架并使用如下的apache commons:

 final List resourceLines = IOUtils.readLines(specialisationResource.getInputStream()); for (final String line : resourceLines) { data.add(getNewTransientSpecialisation(line)); } 

所以请记住,不要使用File()获取资源,总是使用流从开始时避免该问题:-)

希望能帮助别人。

我也遇到了这个限制,并创建了这个库来克服这个问题: spring-boot-jar-resources

它基本上允许您使用Spring Boot注册自定义ResourceLoader,根据需要从JAR中提取类路径资源,透明地:

 new SpringApplicationBuilder() .sources(Application.class) .resourceLoader(new JarResourceLoader()) .run(args); 

使用该ResourceLoader,您可以在任何类路径资源上执行resource.getFile()

现在我需要从JAR中找到xmlFiles到资源文件夹中,并且已经面临类似的问题。 我想分享我的发现以及我是如何工作的,也许它很有帮助。

在一个jar中,我在src / main / resources下有“db-input”文件夹,其中包含用于DB-Input的xml-Files的任何数字。 我的应用程序是基于Spring的:

 @Component public class DatabaseInitializer implements InitializingBean { @Autowired DomainConfigurationRepository repository; @Autowired MarshallerService marshallerService; @Autowired ApplicationContext context; @Override public void afterPropertiesSet() throws Exception { final Resource[] resources = context.getResources("classpath*:db-input/*"); final Set filePaths = findInputFileNames(resources); final Set configurations = createConfigurations(filePaths); repository.save(configurations); } private Set createConfigurations(final Set filePaths) throws Exception { final Set configurations = new HashSet<>(); for(final String path : filePaths){ final Resource resource = context.getResource(path); final DomainConfigurationXO xoConfiguration = marshallerService.unmarshal(resource.getInputStream()); final DomainConfiguration configuration = PopulationUtils.getPopulatedConfiguration(xoConfiguration); configurations.add(configuration); } return configurations; } public Set findInputFileNames(final Resource[] inputDirectoryResources) throws IOException { return Arrays.stream(inputDirectoryResources) .map(resource -> extractURI(resource)) .collect(Collectors.toSet()); } private String extractURI(Resource resource){ try { return resource.getURI().toString(); } catch (IOException e) { throw new RuntimeException(e); } } }