为什么 Jenkins 无法加载资源?
Why Jenkins fails to load the resources?
这是我的项目布局:
src/
test/
resources/
ares/
file1.xml
file2.xml
这是 Jenkins 工作区的布局:
my-module/
target/
test-classes/
ares/
file1.xml
file2.xml
在eclipse下测试运行没有任何错误。
在 Jenkins 上,测试只是失败了。 Jenkins 无法定位资源。
以下是测试执行的一些输出:
日食
MyClass.class.getResourceAsStream(/ares/file1.xml) => java.io.BufferedInputStream@4f4b2f1a
MyClass.class.getResourceAsStream(ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(/ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(ares/file1.xml) => java.io.BufferedInputStream@5d402eeb
MyClass.class.getClassLoader().getResourceAsStream(/ares/file1.xml) => null
MyClass.class.getClassLoader().getResourceAsStream(ares/file1.xml) => java.io.BufferedInputStream@20c87621
詹金斯
MyClass.class.getResourceAsStream(/ares/file1.xml) => null
MyClass.class.getResourceAsStream(ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(/ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(ares/file1.xml) => null
MyClass.class.getClassLoader().getResourceAsStream(/ares/file1.xml) => null
MyClass.class.getClassLoader().getResourceAsStream(ares/file1.xml) => null
如您所见,Jenkins 没有找到我的资源。
我错过了什么?
我终于解决了我的问题。在类路径中,文件名为 /ares/file1.xml
,而在我的代码中我调用文件 /ares/file1.XML
。你注意到大写的 XML
了吗?
在 Windows 上没有区别,因为文件名不区分大小写。
在 Linux 上失败,因为文件名区分大小写。
最终想法,当您在与目标平台不同的平台上编写代码时,更喜欢小写文件名。
我遇到了类似症状但不同原因和不同解决方案的问题。
在我的例子中,问题是 Jenkins 服务器是一台 Windows 机器,服务器上到资源位置的完整路径以 C:\Program Files (x86)\...
和 spaces 开头.如果您需要将 space 编码为 %20
,而不是使用 new File(getClass().getResource(fileName).getFile())
的流,则这些 space 会被编码为 File
。这里 fileName
是一个包含资源名称的字符串。我通过添加对 URLDecoder.decode
的调用解决了这个问题。当没有 space 或您不在 Windows 上时(据我所知),这不会产生任何问题,但是如果您在沿线某处命名。完整的调用是:
new File(URLDecoder.decode(getClass().getResource(fileName).getFile(), "UTF-8"))
我从几个问题中拼凑了这个,但是 none 将所有这些拼凑起来用于 Jenkins 案例,因此我在这里回答。其他相关问答:
- Java: how to get a File from an escaped URL?
- How do you unescape URLs in Java?
- Resource files not found from JUnit test cases
由于我在经过半天的困惑之后才解决了我的问题,所以我来到这里两次,我想我应该添加我的解决方案来帮助未来的旅行者。
Jenkins 作业名称中的空格会中断 Java 项目中资源文件的加载。除非你为了安抚 Jenkins 而专门编写不同的加载代码。
我将其归结为一条非常令人沮丧的建议:不要在 JAVA 项目的 JENKINS 工作名称中放置空格。
你可以把几点放在一起...
第一,如果你在 jenkins 作业的名称中加上 space,那么 jenkins 不会想方设法隐藏那个 space。所以调用你的工作 "My Awesome New Job" 并且工作的路径变为 /home/jenkins/My%Awesome%New%20Job
第二,如果您的资源路径中有 %20,那么您的代码将需要 URL 解码资源路径以便能够加载资源。就像让我到达那里的另一个答案一样:
在我的情况下,这些资源文件仅用于测试,所以我只是用连字符替换了工作名称中的 space。
这是我的项目布局:
src/
test/
resources/
ares/
file1.xml
file2.xml
这是 Jenkins 工作区的布局:
my-module/
target/
test-classes/
ares/
file1.xml
file2.xml
在eclipse下测试运行没有任何错误。 在 Jenkins 上,测试只是失败了。 Jenkins 无法定位资源。 以下是测试执行的一些输出:
日食
MyClass.class.getResourceAsStream(/ares/file1.xml) => java.io.BufferedInputStream@4f4b2f1a
MyClass.class.getResourceAsStream(ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(/ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(ares/file1.xml) => java.io.BufferedInputStream@5d402eeb
MyClass.class.getClassLoader().getResourceAsStream(/ares/file1.xml) => null
MyClass.class.getClassLoader().getResourceAsStream(ares/file1.xml) => java.io.BufferedInputStream@20c87621
詹金斯
MyClass.class.getResourceAsStream(/ares/file1.xml) => null
MyClass.class.getResourceAsStream(ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(/ares/file1.xml) => null
Thread.currentThread().getContextClassLoader().getResourceAsStream(ares/file1.xml) => null
MyClass.class.getClassLoader().getResourceAsStream(/ares/file1.xml) => null
MyClass.class.getClassLoader().getResourceAsStream(ares/file1.xml) => null
如您所见,Jenkins 没有找到我的资源。
我错过了什么?
我终于解决了我的问题。在类路径中,文件名为 /ares/file1.xml
,而在我的代码中我调用文件 /ares/file1.XML
。你注意到大写的 XML
了吗?
在 Windows 上没有区别,因为文件名不区分大小写。 在 Linux 上失败,因为文件名区分大小写。
最终想法,当您在与目标平台不同的平台上编写代码时,更喜欢小写文件名。
我遇到了类似症状但不同原因和不同解决方案的问题。
在我的例子中,问题是 Jenkins 服务器是一台 Windows 机器,服务器上到资源位置的完整路径以 C:\Program Files (x86)\...
和 spaces 开头.如果您需要将 space 编码为 %20
,而不是使用 new File(getClass().getResource(fileName).getFile())
的流,则这些 space 会被编码为 File
。这里 fileName
是一个包含资源名称的字符串。我通过添加对 URLDecoder.decode
的调用解决了这个问题。当没有 space 或您不在 Windows 上时(据我所知),这不会产生任何问题,但是如果您在沿线某处命名。完整的调用是:
new File(URLDecoder.decode(getClass().getResource(fileName).getFile(), "UTF-8"))
我从几个问题中拼凑了这个,但是 none 将所有这些拼凑起来用于 Jenkins 案例,因此我在这里回答。其他相关问答:
- Java: how to get a File from an escaped URL?
- How do you unescape URLs in Java?
- Resource files not found from JUnit test cases
由于我在经过半天的困惑之后才解决了我的问题,所以我来到这里两次,我想我应该添加我的解决方案来帮助未来的旅行者。
Jenkins 作业名称中的空格会中断 Java 项目中资源文件的加载。除非你为了安抚 Jenkins 而专门编写不同的加载代码。
我将其归结为一条非常令人沮丧的建议:不要在 JAVA 项目的 JENKINS 工作名称中放置空格。
你可以把几点放在一起...
第一,如果你在 jenkins 作业的名称中加上 space,那么 jenkins 不会想方设法隐藏那个 space。所以调用你的工作 "My Awesome New Job" 并且工作的路径变为 /home/jenkins/My%Awesome%New%20Job
第二,如果您的资源路径中有 %20,那么您的代码将需要 URL 解码资源路径以便能够加载资源。就像让我到达那里的另一个答案一样:
在我的情况下,这些资源文件仅用于测试,所以我只是用连字符替换了工作名称中的 space。