在部署后,我一直试图引导Java ClassLoader从test/resources
目录检索JSON文件时遇到问题。
public class TestFileUtil {
private static final ClassLoader classLoader = TestFileUtil.class.getClassLoader();
public static Map<String, Object> getJsonFileAsMap(String fileLocation) {
try {
return new ObjectMapper().readValue(getTestFile(fileLocation), HashMap.class);
} catch (IOException e) {
throw new RuntimeException("Error converting JSON file to a Map", e);
}
}
private static File getTestFile(String fileLocation) {
return new File(classLoader.getResource(fileLocation).getFile());
}
}
在使用Mockito进行本地测试期间,该实用程序没有问题,如下所示:
public class LocalTest {
@Before
public void setUp() {
Mockito.when(mockDataRetrievalService.getAssetJsonById(Mockito.any())).thenReturn(TestFileUtil.getJsonFileAsMap("test.json"));
}
}
但是,在我们部署的环境中进行构建时,此行会引发FileNotFound异常。
在使用相对目录路径"../../test.json"
时,在两种环境中都看到FileNotFound异常。
本地目录结构:
test
| java
| |- project
| | |- LocalTest
| |- util
| | |- TestFileUtil.class
| resources
| |- test.json
部署后:
test
| com
| | project
| | | dao
| | | | LocalTest
| | other project
| | | | util
| | | | | TestFileUtil.class
| | | | | test.json
在自动生成中使用ClassLoader是否有任何特殊行为或所需的目录结构?
答案 0 :(得分:1)
问题很可能是这样的:
new File(classLoader.getResource(fileLocation).getFile());
URL类不会的getFile()方法不会返回有效的文件名。它只是返回URL的路径部分,因此不能保证它是有效的文件名。 (当URL类作为Java 1.0的一部分引入时,方法名称才有意义,因为几乎所有URL实际上都引用了同一台计算机上或另一台计算机上的物理文件。)
ClassLoader.getResource的参数不是文件名。这是一个相对URL,其基础是ClassLoader的类路径中的每个位置。如果要读取与应用程序捆绑在一起的资源,请不要尝试将资源URL转换为文件。将该URL读取为URL:
public class TestFileUtil {
private static final ClassLoader classLoader = TestFileUtil.class.getClassLoader();
public static Map<String, Object> getJsonFileAsMap(String fileLocation) {
try {
return new ObjectMapper().readValue(getTestFile(fileLocation), HashMap.class);
} catch (IOException e) {
throw new RuntimeException("Error converting JSON file to a Map", e);
}
}
private static URL getTestFile(String fileLocation) {
return classLoader.getResource(fileLocation);
}
}
如果您想读取不属于应用程序的文件,请不要使用getResource。只需创建一个File实例。