今天在做log4j.xml解析的时候,指定了如下的dtd声明:
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
不过在应用的启动过程中,由于log4j.xml被替换至一个临时目录下,而log4j.dtd没有被跟随拷贝过去,导致解析log4j配置的过程中,抛出了如下的异常信息:
2011-04-27 21:27:03.407:WARN::Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name ....... java.io.FileNotFoundException: C:\Users\lanbo.xj\AppData\Local\Temp\hsf_jetty_placeholder\log4j.dtd (系统找不到指定的文件。) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(FileInputStream.java:106) at java.io.FileInputStream.<init>(FileInputStream.java:66) ......
当解析xml文件时,如果xml文件中引用了dtd文件,解析的时候读不到这个dtd文件,无论解析是否设置验证,都会抛出这样的异常。
所以想到要在解析xml时,禁止校验DTD文件。
我在参考了
1). xml解析忽略dtd文件
2). java解析xml禁止校验dtd
之后,修改了解析XML的代码,我是用DocumentBuilder做解析的,代码如下:
private Document getDocument(String configFile) throws ParserConfigurationException, SAXException, IOException { dbf = DocumentBuilderFactory.newInstance(); db = dbf.newDocumentBuilder(); db.setEntityResolver(new IgnoreDTDEntityResolver()); return db.parse(new File(configFile)); } class IgnoreDTDEntityResolver implements EntityResolver { @Override public InputSource resolveEntity(String arg0, String arg1) throws SAXException, IOException { return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes())); } }
经上述修改后,问题解决。
PS:刚了解到一个情况,与上述文章无关,但碍于另写一篇,就放置于此文之后:
想了解下log4j中log4j.properties和log4j.xml的加载顺序,经过查看LogManager.java
// if the user has not specified the log4j.configuration
// property, we search first for the file "log4j.xml" and then
// "log4j.properties"
明确了,当用户没有设置log4j.configuration属性,则首先查找log4j.xml,然后查找log4j.properties。
log4j.properties以后已经不再推荐使用了。