Java/Maven项目JUnit测试中无法读取Resources目录XSLT文件问题
核心问题分析
你的问题根源在两个地方:Maven资源配置错误导致样式表文件未被正确打包,以及用File类读取打包后资源的方式不符合规范。
1. Maven资源复制/过滤配置异常
项目修改后出现问题,大概率是pom.xml里的<resources>配置被破坏:
- 若开启了
<filtering>true</filtering>但未指定包含文件类型,xslt这类非默认格式的资源可能被过滤丢弃 - 或是
<includes>/<excludes>规则写错,把xslt/mystylesheet.xsl排除在打包范围外 - 另外你看到
target/classes里有xslt文件夹,但可能实际文件并未被复制进去——只是空文件夹被保留了
2. 资源加载方式错误
classLoader.getResource(stylesheetPath).getFile()仅适用于资源在本地文件系统的场景。一旦项目被打包成jar/war,资源是嵌入在包内的,并非独立文件,此时getFile()返回的是jar内部的虚拟路径,用File类根本无法访问。这也是你能获取到xslt文件夹资源,但指定具体文件就失败的原因。
具体修复步骤
步骤1:修正Maven的pom.xml资源配置
确保主代码和测试代码的资源都能被正确复制到目标目录:
<build> <resources> <!-- 主代码资源配置 --> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <!-- 不需要变量替换就设为false,避免破坏xslt文件结构 --> <includes> <include>**/*</include> <!-- 包含所有资源文件,也可以精确指定类型 --> <!-- 比如:<include>xslt/**/*.xsl</include> <include>log4j2.xml</include> --> </includes> </resource> </resources> <testResources> <!-- 测试代码资源配置 --> <testResource> <directory>src/test/resources</directory> <filtering>false</filtering> <includes> <include>**/*</include> </includes> </testResource> </testResources> </build>
配置完成后执行mvn clean compile,再检查target/classes/xslt/下是否确实存在mystylesheet.xsl文件。
步骤2:修改资源加载代码
放弃使用File类,改用getResourceAsStream读取输入流——这是读取类路径资源的标准方式,无论资源在本地文件系统还是jar包内都能正常工作:
private void validateInput(NeptuneXmlPipelineElement input) throws Exception { // 用当前类的类加载器获取输入流,路径前加/表示从类路径根目录开始查找 InputStream is = getClass().getResourceAsStream("/" + stylesheetPath); // 也可以用ClassLoader:InputStream is = getClass().getClassLoader().getResourceAsStream(stylesheetPath); // 注意:ClassLoader的路径不需要加开头的/ if (is == null) { String errorMsg = "unable to locate xslt stylesheet " + stylesheetPath; input.getConversionResult().addMessage(errorMsg); throw new FileNotFoundException(errorMsg); } // 后续直接用InputStream处理XSLT即可,比如传给TransformerFactory // TransformerFactory factory = TransformerFactory.newInstance(); // Transformer transformer = factory.newTransformer(new StreamSource(is)); // ... }
步骤3:验证测试代码的路径传递
你的测试代码中stylesheetPath = "xslt/mystylesheet.xsl"是正确的,确保该路径在传递给validateInput时没有被篡改。
额外排查方法
如果问题仍存在,可以在测试代码中打印类路径和资源URL,确认资源是否真的在类路径中:
@Test public void testPipelineWorkflow() { String stylesheetPath = "xslt/mystylesheet.xsl"; // 打印当前类路径 System.out.println(System.getProperty("java.class.path")); // 验证资源是否存在 URL resource = getClass().getClassLoader().getResource(stylesheetPath); System.out.println("Resource URL: " + resource); }
如果resource为null,说明资源未被正确打包,回到步骤1检查Maven配置;如果有URL但File访问失败,就是加载方式的问题,按步骤2修改即可。
内容的提问来源于stack exchange,提问作者jasonwardenburg

