问题描述
写一个flink实时任务,任务启动时解析资源目录下的xml文件。代码写好了,idea上测试代码也ok,但一提交到集群环境运行的时候,就提示找不到文件。
目录结构如下
示例代码如下
try {
SAXReader saxReader = new SAXReader();
URL url = this.getClass().getResource("/cjm.xml");
File inputXml = new File(url.getFile());
Document document = saxReader.read(inputXml);
……
} catch (DocumentException e) {
logger.error("parse xml fail, msg:" + e.getMessage());
}
运行报错如下
parse xml fail, msg:file:/var/folders/hr/lpgk_yqs5kbg8jfwk6g0n1q40000gn/T/blobStore-aa2516aa-2bf0-4b13-a650-e92c9f5b8628/job_8eaee161599d0d41ceaf95231673fe4c/blob_p-58b0a523357b29468bb5d1d06c642852a4f344e3-b2061c431c14ad68dccdc7f5f3700b16!/cjm.xml (No such file or directory)
java解析文件方法比c++丰富多了,集群环境读取文件比本地环境读取文件又有不少差异。
问题解决
直接上解决后的示例代码
try {
SAXReader saxReader = new SAXReader();
InputStream in = this.getClass().getResourceAsStream("/cjm.xml");
Document document = saxReader.read(in);
……
} catch (DocumentException e) {
logger.error("parse xml fail, msg:" + e.getMessage());
}
问题注意
- 要用getResourceAsStream,不要用getResource,后者在本地运行测试代码的时候可以,提交集群运行的时候就出错了。
- 参数一定要带"/",如文件cjm.xml在resources目录下,参数为"/cjm.xml";如文件cjm.xml在resources/file目录下,参数则为"/file/cjm.xml"。
- pom文件下面一段可以不需要,有些文章提到添加这段,实测不必。
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
- 有空的话研究下面几种读取资源文件的差别。网上也能搜到很多文章,但很多也有问题,还是自己验证比较靠谱。
this.getClass().getResource("cjm.xml");
this.getClass().getResource("/cjm.xml");
this.getClass().getClassLoader().getResource("cjm.xml");
this.getClass().getClassLoader().getResource("/cjm.xml");