针对因accessExternalDTD属性限制导致无法通过HTTP访问外部DTD(如MyBatis的mybatis-3-mapper.dtd)的问题,以下是详细的解决方案: 问题原因 Java XML解析器默认禁止从……
针对因accessExternalDTD
属性限制导致无法通过HTTP访问外部DTD(如MyBatis的mybatis-3-mapper.dtd
)的问题,以下是详细的解决方案:
问题原因
Java XML解析器默认禁止从外部加载DTD(防止XXE攻击),因此当XML文件尝试通过HTTP访问远程DTD(如<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">)时,会抛出以下错误:
org.xml.sax.SAXParseException: 外部 DTD: 无法读取外部 DTD 'mybatis-3-mapper.dtd', 因为 accessExternalDTD 属性设置的限制导致不允许 'http' 访问
解决方案
根据需求选择以下任意一种方法:
1. 在代码中配置XML解析器(推荐)
在创建DocumentBuilder
或SAXParser
时,显式允许访问HTTP协议的DTD:
import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; public class XmlParser { public static void main(String[] args) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 关键配置:允许通过HTTP访问外部DTD factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "http"); DocumentBuilder builder = factory.newDocumentBuilder(); builder.parse("input.xml"); // 解析XML文件 } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } } }
2. 通过JVM参数全局配置
在启动应用时添加以下参数,允许所有XML解析器访问HTTP/HTTPS协议的外部DTD:
java -Djavax.xml.accessExternalDTD=http,https -jar YourApp.jar
3. 使用本地DTD文件(安全推荐)
避免依赖远程DTD,将mybatis-3-mapper.dtd
下载到本地,并修改XML的DOCTYPE声明指向本地路径:
-
下载DTD文件
访问 http://mybatis.org/dtd/mybatis-3-mapper.dtd 并将文件保存到项目目录(如src/main/resources/dtd/mybatis-3-mapper.dtd
)。 -
修改XML声明
将XML中的DOCTYPE路径替换为本地路径: -
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "classpath:/dtd/mybatis-3-mapper.dtd">
4. 完全禁用DTD(极端情况)
如果无需DTD验证,可直接禁用外部实体解析:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); // 启用安全处理 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 禁用DOCTYPE
注意事项
-
安全风险
允许外部DTD访问可能引发XXE攻击,确保仅加载可信来源的DTD。 -
兼容性
部分旧版XML解析器(如Apache Xerces 1.x)可能不支持ACCESS_EXTERNAL_DTD
属性,建议升级到较新版本。 -
MyBatis框架集成
若在MyBatis中遇到此问题,建议优先使用本地DTD文件,避免因网络问题导致解析失败。
这里建议使用第三种方法,比较简单,也安全可靠!
还没有评论呢,快来抢沙发~