问题提出 :
解析ejb-jar.xml,出现在网络连不上的情况下,解析失败的情况。
问题分析:
我们使用的是DOM进行XML的解析的:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//位置点
Document doc = builder.parse(file);
由于ejb-jar.xml中,有
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
在解析的时候,会从网络http://java.sun.com/dtd/ejb-jar_2_0.dtd中抓紧DTD文件,进行验证,如果网络不通,那么就会出现解析失败。
首先,DocumentBuilderFactory.newInstance()创建DocumentBuilderFactory实现类的对象,它会通过一下方式来查找实现类:
1.在系统环境变量中(System.getProperties())中查找 key=javax.xml.parsers.DocumentBuilderFactory
2.如果1没有找到,则找java.home/lib/jaxp.properties 文件,如果文件存在,在文件中查找key=javax.xml.parsers.DocumentBuilderFactory
3.如果2没有找到,则在classpath中的所有的jar包中查找META-INF/services /javax.xml.parsers.DocumentBuilderFactory 文件
全都没找到,则返回null
如果上面都没有找到,那么就使用JDK自带的实现类:
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
在创建DocumentBuilder实例的时候,是根据DocumentBuilderFactoryImpl的不同有不同的实现。
为了在网络不可用的情况下,正常解析XML文件,我们可以在使用builder之前,设置EntityResolver:
builder.setEntityResolver(
new EntityResolver(){
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
{
return new InputSource(new StringBufferInputStream(""));
// return null;//这个的效果仍然是从网络来抓取DTD来验证
}
}
);
上面的设置就不会对XML文件进行验证。
如果一定要验证的话,我们也可以设置使用本地的DTD文件来做验证:
builder.setEntityResolver(
new EntityResolver(){
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
{
if(publicId.equals("-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"))
{
String dtd_uri = "C:/TEMP/ejb-jar_2_0.dtd";
return new InputSource(dtd_uri);
}
}
);
注意:直接return null,仍然会从网络来抓取DTD来验证。