可执行的Spring Boot jar中的资源未加载 - 可执行jar如何加载资源?

8

我正在尝试根据这里提供的文档来运行可执行的基于Spring的jar包。我希望在运行时能够将资源复制到可执行的jar包中。

mvn clean package

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

./my-application.jar

在我的项目中,我有一个批处理过程,在启动时运行,我正在尝试加载在

中定义的资源。

src/main/resources/batch/request_customers.csv

这是我加载资源application.properties的方式:

data.customers.input=classpath:batch/request_customers.csv

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);
    }


}

错误日志
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 

我也尝试了以下路径

data.customers.input=src/resources/batch/request_customers.csv
data.customers.input=batch/request_customers.csv

当我使用我的IDE和Spring插件运行应用程序时,资源可以正常加载。但是当我使用./my-application.jar运行可执行jar包时会出现问题。
问题在于如何确保将所有资源复制到我打包的jar文件中?
我需要进行其他配置以告诉Maven按其结构复制资源吗?
我该如何检查资源是否已经打包进了jar文件?由于某些原因我无法提取jar文件。
我希望知道如何构建一个可执行的jar文件,它基本上像一个可执行文件一样工作。
更新: 该文件存在于应该被加载的jar文件中。我没有从外部文件路径加载。
BOOT-INF/classes/batch/request_customers.csv

这里是解决方案

当您构建一个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);
}

1
你尝试过 data.customers.input=classpath:/batch/request_customers.csv 吗?注意在 classpath 前面有一个斜杠 '/'。 - Sangram Jadhav
我尝试使用batch/request_customers.csv,但它没有起作用。 - amjad
你能确认一下 CSV 文件是否包含在打包的 Jar 文件中吗? - Sangram Jadhav
我该怎么做? - amjad
所以需要使用 classpath:。 - Joop Eggen
显示剩余4条评论
2个回答

10

由于文件位于jar包中而不是文件系统中,因此无法获取文件引用。

您可以采用以下方式之一将其作为流进行读取:

ResourceUtils.getURL(usersExistingData).openStream()

文件在JAR包的类路径中。我正在使用相对路径。 - amjad
不过它并不是一个文件,你不能像使用文件对象一样简单地引用Java中的资源。 - linead
抱歉给您带来负面影响,这是一个错误。请编辑,我会更改分数。 - amjad

6

不要使用ResourceUtil,请考虑使用ResourceLoader,如ResourceUtil文档所述。

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. 

所以你的类应该像这样:
```

所以你的类应该像这样:

```
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();
    }


}

你能把第二行的代码格式去掉吗?那样看起来很难读。 - Saurabh
请注意,使用ResourceLoader需要ApplicationContext,如果您需要在Spring Boot应用程序启动之前加载资源,则无法正常工作。 - Kobynet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接