如何从多个项目访问公共资源文件
Posted
技术标签:
【中文标题】如何从多个项目访问公共资源文件【英文标题】:How to access common resource files from multiple projects 【发布时间】:2014-02-14 10:28:28 【问题描述】:在我的一个项目中,我将资源存储在 /src/test/resources
(典型的 maven 目录结构)中。存储在项目中的实用程序类正在使用这些资源。
实用程序类本身正被其他项目使用(其他项目依赖于这个)。我会这样访问资源:
final InputStream inputStreamDobs =
ClassLoader.class.getResourceAsStream("/dbunit/clear_db.xml");
但由于我在不同的项目中使用它,所以路径不正确 - 它与 current project that is being built/tested
相关,而不是实用程序类和资源所在的路径。
有没有想过如何解决这个问题?
我需要避免使用绝对路径 - 希望有一种方法可以定义实用程序类的相对路径。
我也不想在多个项目中复制资源。干杯。
编辑: 为了给出上下文,我在 XML 文件中定义了需要在集成测试后清除的表(清除整个数据库模式)。集成测试位于多个项目中,但清晰的脚本和资源文件对所有项目都是相同的,并且位于共同的父项目中。
EDIT2:
额外问题:我想访问需要从多个其他项目的 XML 文件访问的常见 DTD 文件(我们称之为tables.dtd
)。 (它将位于共同的父项目中)。
目前我将它复制到多个项目中,我使用指令从 XML 中引用它:
<!DOCTYPE dataset SYSTEM "src/test/resources/dbunit/dobs.dtd">
如何将其指向不同项目中的文件?
【问题讨论】:
【参考方案1】:你写的
...但是由于我在不同的项目中使用它,所以路径不正确 - 它与正在构建/测试的当前项目相关,而不是实用程序类和资源所在的项目 ...
相对路径不是这里的问题。您在示例中使用了绝对路径,但即使您使用相对路径,这也将引用包或目录结构。只要类路径正确,getResourceAsStream
就会选择它们。真正的问题是您指的是另一个项目中的测试资源。但是测试资源和类不包含在项目工件中,因此无法从包含此依赖项的模块访问它们。如果您需要这些资源在多个项目中进行测试,我建议您使用包含在 src/main/resources
中的这些资源创建一个新项目(比如说“projectxyz-testresources”),并将其添加为范围为“test”的相关项.
编辑添加:
如果您不想为测试资源使用单独的项目,您可以使用目标jar:test-jar
创建一个包含测试类和资源的测试jar,并将其作为测试依赖项包含在内。您可能需要在 pom 中配置 jar 插件以在常规构建中执行此目标。
【讨论】:
怎么回事?我使用相对路径..它是相对于项目根目录的。 (?) getResourceAsStream 尝试从类路径加载资源。它是绝对的,因为它从每个类路径条目的根开始搜索。相对路径不会以斜杠开头,而是相对于当前包进行搜索。所以你的路径对于你的文件系统不是绝对的,但在 Java 意义上是绝对的。【参考方案2】:您的运行时类路径不应引用 src/test/resources。 Maven 会将所有内容复制到目标,因此您应该能够使用“/dbunit/clear_db.xml”获取它
【讨论】:
没错,我复制粘贴的错误。但问题仍然有效。 该绝对路径对于类路径根是“绝对的”。所以如果你把它放在一个 jar 甚至一个分解的目录中,它将通过类路径而不是磁盘上的任何特定位置找到。因此,只要您的类路径正确,该路径就可以在每次安装中移植。 但是不同项目的类路径是不同的,对吧? (我有丰富的 Maven 模块层次结构) 类路径会有所不同,例如,Windows 文件系统上的 jar 路径与 linux 上的路径不同。但是对于您的应用程序来说,它只是一个类路径,因此您的代码不会受到此类变化的影响,并且可以编写一次并在任何地方运行。 但是这些项目(模块)是单独构建的。我最感兴趣的是 maven 的集成测试阶段,因为这个 Util 类用于测试(使用 dbunit)。【参考方案3】:您是否尝试过使用“classpath:”前缀?如果资源在类路径中可用,则不必指定资源的完整路径。例如:
<mvc:resources location="classpath:/META-INF/web-resources/" mapping="/resources/**" />
/META-INF/web-resources/ 来自 Spring MVC 的 JAR,它是项目的依赖项之一。该项目不需要知道如何“直接”访问该资源,而是使用类路径。
【讨论】:
【参考方案4】:我认为您可以为此目的使用以下 2 个插件。
如果您的项目是 web 项目,您可以创建 2 个 web 项目,其中一个包含配置文件,另一个项目是您的主项目,现在您可以使用 maven-war-plugin
覆盖项目
叠加有多种类型,您可以访问此页面了解更多信息 maven-war-plugin overlay
对于 jar 文件,您可以使用 maven-assembly-plugin
将它们合并为单个文件
maven-assembly-plugin
【讨论】:
【参考方案5】:我们有一个类似的实例,其中我们有一些配置文件在大型多模块 maven 项目中的多个模块中使用。 所以我们所做的就是将 conf 文件拆分为一个单独的模块,它只是将配置文件打包起来。 然后任何需要这些文件的模块都可以声明对配置文件模块的依赖关系,只需将 jar 文件与配置文件一起使用并解压缩即可使用它们。 您可以为测试资源做类似的事情。创建一个仅包含资源的模块,然后将它们放入相关路径中。
【讨论】:
【参考方案6】:在这种情况下,我建议为此任务编写一个 maven 插件,以便可以通过属性配置这个可变路径。 您还将受益于 Project 对象。
/**
* Location of the file.
*/
@Parameter(defaultValue = "$basedir/src/main/java", property = "sourceFolder", required = true)
private File sourceFolder;
@Parameter(defaultValue = "$basedir/src/test/java", property = "testFolder", required = true)
private File testFolder;
@Parameter(defaultValue = "$project", property = "project", readonly = true, required = true)
private MavenProject project;
【讨论】:
我会试试这个(可能在周末之后)并给你一个更新,但我认为它可能会起作用。谢谢! @Hannes - 您的应用程序不应该知道用于构建它的构建工具或该工具预期的文件夹结构。如果您想使用来自另一个项目的资源,该资源不属于您的代码库或不使用 maven 的布局,该怎么办? Java 的类路径为您执行此操作,而无需了解项目布局。 @ike_love 原谅?我无法跟随你的想法。 @Hannes - 您的解决方案使用绝对路径,并且仅适用于在构建期间爆炸的 JAR 中的资源。使用 JAR 中资源的标准 Java 方式是使用类路径,而不是分解 jar 并直接引用该资源。 @Hannes - 无需编写插件即可在 JAR 之间共享资源,该机制已经存在 - 类路径。【参考方案7】:您可以尝试使用 Maven Overlays 吗?我们过去也遇到过类似的情况,并且使用覆盖解决了很多问题。通常,叠加层用于在多个 Web 应用程序之间共享公共资源。
【讨论】:
【参考方案8】:也许是这些方法之一:
要么:您将需要访问它们的 xml 文件和 java 类(如实用程序类)外包到一个单独的库中,然后您可以将其包含到您的其他几个项目中(方便地作为 maven 依赖项)。
或者:您将这些 xml 文件放入单独的 VCS 树或存储库中,并将它们包含在您的项目树中(例如,作为 SVN 中的“外部”)。所以你可以在你的项目中单独更新这个引用,但你只需要维护一个源文件。
【讨论】:
以上是关于如何从多个项目访问公共资源文件的主要内容,如果未能解决你的问题,请参考以下文章