资源没有加载到可执行文件Spring boot jar中 - 可执行jar如何加载资源?

amj*_*jad 7 java spring spring-boot

我试图根据此处提供的文档运行可执行启动弹簧jar .我期待资源将被复制到运行时的可执行jar

mvn clean package
Run Code Online (Sandbox Code Playgroud)

以下是我在项目文件夹下运行.jar的方法

./my-application.jar
Run Code Online (Sandbox Code Playgroud)

在我的项目中,我有一个在启动时运行的批处理,我正在尝试加载在其下定义的资源

src/main/resources/batch/request_customers.csv
Run Code Online (Sandbox Code Playgroud)

这是我如何加载资源 application.properties

data.customers.input=classpath:batch/request_customers.csv
Run Code Online (Sandbox Code Playgroud)

import org.springframework.util.ResourceUtils;
@Component
public class DataManager {

    @Value("${data.customers.input}")
    private String usersExistingData;

    public File jsonCustomerData() throws FileNotFoundException {
        return  ResourceUtils.getFile(usersExistingData);
    }


}
Run Code Online (Sandbox Code Playgroud)

错误日志

s]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.groupon.batch.CustomerItemReader]: Factory method 'reader' threw exception; nested exception is java.io.FileNotFoundException: class path resource [batch/request_customers.csv] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/Users/xxx/projects/myproject/target/myproject-0.0.2-SNAPSHOT.jar!/BOOT-INF/classes!/batch/request_customers.csv; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'job' defined in class path resource [com/mycompany/batch/BatchConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'job' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'step1' defined in class path resource [com/mycompany/batch/BatchConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Step]: Factory method 'step1' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reader' defined in class path resource 
Run Code Online (Sandbox Code Playgroud)

我也尝试过以下路径

data.customers.input=src/resources/batch/request_customers.csv
data.customers.input=batch/request_customers.csv
Run Code Online (Sandbox Code Playgroud)

当我使用我的IDE和spring插件运行应用程序时,资源加载没有任何问题.但是当我使用./my-application.jar运行可执行jar时失败

  • 问题是如何在打包时确保所有资源都是jar的副本?
  • 我是否需要做一些其他配置来告诉maven复制资源?
  • 我如何检查资源是否包装到jar中?我出于某些原因无法提取罐子?

很高兴知道我究竟能够构建一个基本上像可执行文件一样工作的可执行jar .

UPDATE 文件存在于应加载的jar中.我没有从外部文件路径加载.

BOOT-INF/classes/batch/request_customers.csv
Run Code Online (Sandbox Code Playgroud)

这是解决方案

当您构建一个jar文件并部署到一个路径时,您需要将资源视为文件系统 - 相对路径不会神奇地加载资源,这正是我所期待的.您必须以流方式打开并阅读它们.这是一种方法

StringBuffer buffer = new StringBuffer();

BufferedReader inputStream =
        new BufferedReader(new InputStreamReader(resourceloader.getResource(file).getInputStream()));

String line = null;

while ((line = inputStream.readLine()) != null){
    buffer.append(line);
}
Run Code Online (Sandbox Code Playgroud)

lin*_*ead 6

您无法获取文件引用,因为该文件位于jar(而不是文件系统)中。

最好的办法是使用以下命令将其作为流读取:

ResourceUtils.getURL(usersExistingData).openStream()
Run Code Online (Sandbox Code Playgroud)


Gok*_*ner 6

而不是ResourceUtil考虑使用ResourceLoaderResourceUtil doc上的说明

Consider using Spring's Resource abstraction in the core package for handling all kinds of file resources in a uniform manner. org.springframework.core.io.ResourceLoader's getResource() method can resolve any location to a org.springframework.core.io.Resource object, which in turn allows one to obtain a java.io.File in the file system through its getFile() method. 
Run Code Online (Sandbox Code Playgroud)

所以你的课应该是这样的:

import org.springframework.core.io.ResourceLoader;
@Component
public class DataManager {

    @Autowired
    ResourceLoader resourceloader;

    @Value("${data.customers.input}")
    private String usersExistingData;

    public File jsonCustomerData() throws IOException{
        return  resourceloader.getResource(usersExistingData).getFile();
    }


}
Run Code Online (Sandbox Code Playgroud)