使用 maven-shade-plugin 读取资源文件 uber jar build

Reading resource file uber jar build with maven-shade-plugin

我有一个读取资源 .yaml 文件的简单项目:

var yamlObjectMapper = new ObjectMapper(new YAMLFactory());
var classLoader = Application.class.getClassLoader();
var file = new File(Objects.requireNonNull(classLoader.getResource("config.yaml")).getFile());
var appConfig = yamlObjectMapper.readValue(file, ApplicationConfig.class);

所以它从 IDE 开始工作正常。现在我想构建一个可执行的 uber JAR,它将包含里面的所有资源。我正在使用 maven-shade-plugin.

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <minimizeJar>true</minimizeJar>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>mypackage.Application</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

所以我希望资源文件包含在 jar 中。当我执行 jar tf myapplication-0.0.1-SNAPSHOT.jar 时,我可以看到在 jar 中有文件 config.yaml。但是,当我尝试使用 java -jar 对它进行 运行 时,我收到 java.io.FileNotFoundException 消息,其中包含无法找到 config.yaml 的消息。

这是 Andrea Boccacci 提供给我的解决方案。这是他允许我在这里 post 的回答:

您的文件在 jar 文件中,因此您无法从 File 访问它 class 尝试使用 getResourceAsStream 然后切换到 readValue(InputStream, Class) 如果有这样的一个 API。 如果不是,您可以将输入流写入实际的临时文件,然后调用 readValue(File, Class) 然后删除提取的文件。

下面是我的代码现在的样子和它的工作原理:

var yamlObjectMapper = new ObjectMapper(new YAMLFactory());
var classLoader = Application.class.getClassLoader();
var resource = classLoader.getResourceAsStrean("config.yaml");
var appConfig = yamlObjectMapper.readValue(resource, ApplicationConfig.class);