简体   繁体   English

读取 Spring boot fat jar 内的文件

[英]Reading file inside Spring boot fat jar

We have a spring boot application which has a legacy jar api that we use that needs to load properties by using InputFileStream.我们有一个 spring boot 应用程序,它有一个遗留的 jar api,我们使用它需要使用 InputFileStream 加载属性。 We wrapped the legacy jar in our spring boot fat jar and the properties files are under BOOT-INF/classes folder.我们将遗留 jar 包在我们的 spring boot fat jar 中,属性文件位于 BOOT-INF/classes 文件夹下。 I could see spring loading all the relevant properties but when I pass the properties file name to the legacy jar it could not read the properties file as its inside the jar and is not under physical path.我可以看到 spring 加载了所有相关的属性,但是当我将属性文件名传递给遗留 jar 时,它无法读取属性文件作为它在 jar 内部并且不在物理路径下。 In this scenario how do we pass the properties file to the legacy jar?在这种情况下,我们如何将属性文件传递给遗留 jar?

Please note we cannot change the legacy jar.请注意,我们无法更改旧 jar。

I also have faced this issue recently.我最近也遇到了这个问题。 I have a file I put in the resource file, let's call it path and I was not able to read it.我有一个文件放在资源文件中,我们称之为path ,但我无法读取它。 @madoke has given one of the solutions using FileSystem. @madoke 给出了使用 FileSystem 的解决方案之一。 This is another one, here we are assuming we are in a container, and if not, we use the Java 8 features.这是另一个,这里我们假设我们在一个容器中,如果不是,我们使用 Java 8 特性。

@Component 
@Log4j2
public class DataInitializer implements 
    ApplicationListener<ApplicationReadyEvent> {

private YourRepo yourRepo; // this is your DataSource Repo

@Value(“${path.to.file}”). // the path to file MUST start with a forward slash: /iaka/myfile.csv
private String path;

public DataInitializer(YourRepo yourRepo) {
    this.yourRepo = yourRepo;
}

@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
    try {
        persistInputData();
        log.info("Completed loading data");
    } catch (IOException e) {
        log.error("Error in reading / parsing CSV", e);
    }
}

private void persistInputData() throws IOException {
    log.info("The path to Customers: "+ path);
    Stream<String> lines;
    InputStream inputStream = DataInitializer.class.getClassLoader().getResourceAsStream(path);
    if (inputStream != null) { // this means you are inside a fat-jar / container
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        lines = bufferedReader.lines();
    } else {
        URL resource = this.getClass().getResource(path);
        String path = resource.getPath();
        lines = Files.lines(Paths.get(path));
    }

    List<SnapCsvInput> inputs = lines.map(s -> s.split(","))
                                     .skip(1) //the column names
                                     .map(SnapCsvInput::new)
                                     .collect(Collectors.toList());
    inputs.forEach(i->log.info(i.toString()));
    yourRepo.saveAll(inputs);

}

}

Actually you can, using FileSystem .其实你可以,使用FileSystem You just have to emulate a filesystem on the folder you need to get the file from.您只需要在需要从中获取文件的文件夹上模拟文件系统。 For example if you wanted to get file.properties , which is under src/main/resources you could do something like this:例如,如果您想获取src/main/resources下的file.properties ,您可以执行以下操作:

FileSystem fs = FileSystems.newFileSystem(this.getClass().getResource("").toURI(), Collections.emptyMap());
String pathToMyFile = fs.getPath("file.properties").toString();
yourLegacyClassThatNeedsAndAbsoluteFilePath.execute(pathToMyFile)

Basically, you can't, because the properties "file" is not a file, it's a resource in a jar file, which is compressed (it's actually a .zip file).基本上,你不能,因为属性“文件”不是一个文件,它是一个 jar 文件中的资源,它被压缩(它实际上是一个 .zip 文件)。

AFAIK, the only way to make this work is to extract the file from the jar, and put it on your server in a well-known location. AFAIK,使这项工作的唯一方法是从 jar 中提取文件,并将其放在您的服务器上的一个众所周知的位置。 Then at runtime open that file with an FileInputStream and pass it to the legacy method.然后在运行时使用 FileInputStream 打开该文件并将其传递给遗留方法。

I wanted to read a JSON file from the resources folder.src/main/resources Hence written a code something like this below. 我想从resources文件夹中读取一个JSON文件。src / main / resources因此在下面编写了类似这样的代码。

Spring Boot Reading Resources in spring boot doesnt works well with fat jar. Spring Boot Reading Spring Boot中的参考资源不适用于胖子。 After spending lot of time in to this simple things there is something i found working below . 在花了很多时间处理这些简单的事情之后,我发现下面的工作。

I have found a detailed link on reading resources in Spring Boot , in case of fat jar . 如果发胖了,我在Spring Boot中找到了阅读资源详细链接

    @Value("classpath:test.json")
    Resource resourceFile;

    try {
             InputStream resourcee =resource.getInputStream();
             String text = null;
                try (final Reader reader = new InputStreamReader(resourcee)) {
                    text = CharStreams.toString(reader);
                }

            System.out.println(text);

        } catch (IOException e) {

            e.printStackTrace();
        }

According to @moldovean's solution, you just need to call 'getResourceAsStream(path)' and continue with returned InputStream.根据@moldovean 的解决方案,您只需要调用“getResourceAsStream(path)”并继续返回的InputStream。 Be aware that the 'path' is based on ClassPath.请注意,“路径”基于 ClassPath。 For example:例如:

InputStream stream = this.getClass().getResourceAsStream("/your-file.csv");

In root of your class path, there is a file named 'your-file.csv' that you want to read.在类路径的根目录中,有一个名为“your-file.csv”的文件要读取。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM