最近使用apache的common configuraton组件解析XML出现连接出错问题,经过检查发现是由于每次解析都需要下载dtd,而这边网络又存在问题所以引起的,结果就是异常如下
org.apache.commons.configuration.ConfigurationException: Connection timed out: connect
at org.apache.commons.configuration.XMLConfiguration.load(XMLConfiguration.java:539)
at org.apache.commons.configuration.XMLConfiguration.load(XMLConfiguration.java:497)
at org.apache.commons.configuration.XMLConfiguration$XMLFileConfigurationDelegate.load(XMLConfiguration.java:921)
at org.apache.commons.configuration.AbstractFileConfiguration.load(AbstractFileConfiguration.java:275)
at org.apache.commons.configuration.AbstractFileConfiguration.load(AbstractFileConfiguration.java:207)
at org.apache.commons.configuration.AbstractFileConfiguration.load(AbstractFileConfiguration.java:185)
at org.apache.commons.configuration.AbstractHierarchicalFileConfiguration.load
....
查看帮助XMLConfiguration具备setValidating方法设置为不校验setValidating(false); 再次运行发现还是需要下载,同样的错误,看来要寻找其他的方法了
检查了一下XMLConfiguration的源代码,发现protected DocumentBuilder createDocumentBuilder()方法用于构造DocumentBuilder,可以实现一个不访问网络的DocumentBuilder,只需要修改这个方法的实现,替换dtd的uri为本地就可以了
扩展了一个自己的XMLConfiguration,将dtd文件放在本地classes的根目录下,使用此解析器解析XML,经过测试,成功,代码如下
public class MyXMLConfiguration extends XMLConfiguration {
private final static String registrations[] = {
"-//SPRING//DTD BEAN 2.0//EN",
"/spring-beans-2.0.dtd" };
protected DocumentBuilder createDocumentBuilder()
throws ParserConfigurationException {
if (getDocumentBuilder() != null) {
return getDocumentBuilder();
} else {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setValidating(isValidating());
DocumentBuilder result = factory.newDocumentBuilder();
result.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId,
String systemId) throws SAXException, IOException {
for (int i = 0; i < registrations.length; i += 2) {
if (publicId.equals(registrations[i])) {
String dtd_uri = registrations[i + 1];
InputStream dtd_stream = this.getClass()
.getResourceAsStream(dtd_uri);
return new InputSource(dtd_stream);
}
}
return null;
}
});
if (isValidating())
{
// register an error handler which detects validation errors
result.setErrorHandler(new DefaultHandler()
{
public void error(SAXParseException ex) throws SAXException
{
throw ex;
}
});
}
return result;
}
}
}