使用依赖项的资源?

2022-09-01 00:08:03

在我的 Maven 项目中,有一个模块(核心)为其类提供了一些资源。在模块内运行类时,它能够获得自己的资源。一切都很好。

当另一个依赖于核心的模块试图运行该类时,东西就会中断。Java 在其中查找资源的文件夹是此模块,而不是核心模块。所以这个类失败了。

简而言之:如何访问依赖项的资源?


我已经尝试过通过在Core的JAR Manifest中声明来做到这一点。但是,当列出可用的资源时(JSHookLoader在Core中,如果它意味着什么),我得到:Class-Path: .JSHookLoader.class.getClassLoader().getResources("");

Resource: W:\programming\quackbot-hg\impl\target\classes
File rebel.xml

Resource: W:\programming\maven-repo\org\quackbot\core\3.5-SNAPSHOT
File core-3.5-SNAPSHOT.jar
File core-3.5-SNAPSHOT.pom
File maven-metadata-local.xml
File _maven.repositories

这当然使事情复杂化,因为我期望JAR本身在类路径中,而不是JAR所在的目录中。

有什么建议吗?


回到这个项目,我仍然有这个问题。其他指南已经讨论了使用maven-assembly-plugin和远程资源插件,但这非常痛苦,因为所有模块都必须包含monster插件XML。

我为什么不把问题简化为:如何将依赖项 JAR 添加到资源列表中?

  1. core.jar在文件夹/resources下有一些资源。运行核心.jar我可以在资源列表中看到 /resources。
  2. impl.jar取决于核心.jar。运行它时,尽管/resources不在资源列表中,因此会造成严重破坏。

这应该很简单,但我该怎么做呢?我花了几个小时试图找出一种简单干净的方式来做到这一点,但无济于事。


答案 1

经过大量的搜索,我终于偶然发现了一个解决方案。

我的解决方案采用核心模块,并使用 Maven Dependency Plugin 将其解压缩,确保排除 META-INF 文件夹和已编译类所在的组织文件夹。我排除我不想要的东西而不是明确说明我想要的东西的原因是,这样就可以很容易地添加新资源,而不必一直更新我的POM。

我没有使用汇编插件或远程资源插件的原因是因为它们使用专用的资源模块。我不认为我应该制作一个核心模块和一个核心资源模块,核心资源模块只包含logback和休眠配置文件+一些其他东西。

这是我用来执行此操作的副本

    <build>
        <plugins>
            <!--Extract core's resources-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.2</version>
                <executions>
                    <execution>
                        <id>unpack</id>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <configuration>
                            <includeGroupIds>${project.groupId}</includeGroupIds>
                            <includeArtifactIds>core</includeArtifactIds>
                            <excludeTransitive>true</excludeTransitive>
                            <overWrite>true</overWrite>
                            <outputDirectory>${project.build.directory}/core-resources</outputDirectory>
                            <excludes>org/**,META-INF/**,rebel.xml</excludes>
                            <overWriteReleases>true</overWriteReleases>
                            <overWriteSnapshots>true</overWriteSnapshots>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <!--New resource locations-->
        <resources>
            <resource>
                <filtering>false</filtering>
                <directory>${project.build.directory}/core-resources</directory>
            </resource>
            <resource>
                <filtering>false</filtering>
                <directory>${basedir}/src/main/resources</directory>
            </resource>
        </resources>
    </build> 

答案 2

如果资源位于 中,并且 JAR 中的类使用 getResourceAsStream() 访问它们,则您也应该能够从其他 JAR 中的类访问这些文件(也使用 )。这是因为位于 中的所有文件最终都位于同一逻辑目录中 ()。换句话说:位于 中的所有文件和编译的所有类都可以说合并到一个命名空间中。/src/main/resourcesgetResourceAsStream()/src/main/resourcesCLASSPATH/src/main/resources/src/main/java

如果即使所有类都使用统一 API,仍然无法访问文件,则可能存在一些类加载可见性问题。getResourceAsStream()


推荐