关于Java EE应用中xml解析类的问题
在Java EE应用中常遇到针对xml文件的处理,而针对这种处理有JDK自带的类,开源组件自带的实现类。 由于从JDK1.8移植到JDK11以上 JDK默认不带一些类,从weblogic、websphere、tomcat移植到TongWeb上,默认的xml解析类不同导致一些解析问题。
如下把一些常用的xml解析类列出来,供大家参考,当出现xml解析问题时,要根据实际应用调整。
| xml解析参数 |
|---|
|
#JDK1.8默认实现类 -Djavax.xml.parsers.DocumentBuilderFactory=com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl #开源xerces.jar实现类 -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl |
|
#JDK1.8默认实现类 -Djavax.xml.stream.XMLInputFactory=com.sun.xml.internal.stream.XMLInputFactoryImpl #开源实现类 -Djavax.xml.stream.XMLInputFactory=com.ctc.wstx.stax.WstxInputFactory -Djavax.xml.stream.XMLInputFactory=com.bea.xml.stream.MXParserFactory |
|
#JDK1.8默认实现类 -Djavax.xml.stream.XMLOutputFactory=com.sun.xml.internal.stream.XMLOutputFactoryImpl #开源实现类 -Djavax.xml.stream.XMLOutputFactory=com.ctc.wstx.stax.WstxOutputFactory |
|
#JDK1.8默认实现类 -Djavax.xml.bind.JAXBContext=com.sun.xml.internal.bind.v2.ContextFactory #开源实现类 -Djavax.xml.bind.JAXBContext=com.sun.xml.bind.v2.ContextFactory #weblogic默认实现类。 xml的双引号会转义成 -Djavax.xml.bind.JAXBContext=org.eclipse.persistence.jaxb.JAXBContextFactory #jakarta命名空间的 -Djakarta.xml.bind.JAXBContext=org.glassfish.jaxb.runtime.v2.ContextFactory |
|
#JDK1.8默认实现类 -Djavax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl #开源实现类 -Djavax.xml.parsers.SAXParserFactory=com.ctc.wstx.sax.WstxSAXParserFactory |
|
#JDK1.8默认实现类 -Djavax.xml.datatype.DatatypeFactory=com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl #开源实现类 -Djavax.xml.datatype.DatatypeFactory=org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl |
|
#开源实现类 -Djavax.xml.soap.SAAJMetaFactory=com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl #JDK1.8默认值 -Djavax.xml.soap.SAAJMetaFactory=com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl |
通常xml解析实现类的优先级由高到低依次为:
1. 以-D参数指定的类为最优先。
2. 其次,若无-D参数,则以jar文件META-INF/services目录下设置的为准,如图。(META-INF/services 文件夹是 Java 的「自动服务发现」目录,用来实现 SPI(Service Provider Interface)机制)

3. 若无以上配置,则以代码中指定为准。
案例1:
应用在TongWeb下报错如下:
Caused by: jakarta.xml.bind.JAXBException:
Exception Description: Invalid XmlElementRef on property rPrOrAliasOrLock on class org.docx4j.wml.SdtPr. Referenced Element not declared.
at com.tongweb.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:1151)
at com.tongweb.persistence.jaxb.JAXBContext.<init>(JAXBContext.java:186)
at com.tongweb.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:153)
at com.tongweb.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:140)
at com.tongweb.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:100)
at com.tongweb.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:90)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:262)
at jakarta.xml.bind.ContextFinder.newInstance(ContextFinder.java:249)
at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:456)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:656)
at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:599)
at com.glodon.ureport.customize.WordDefaultStyle.setTheme4NoItalic(WordDefaultStyle.java:59)
可以看出的问题是:
1. 是 jakarta.xml.bind.JAXBContext,而不是 javax.xml.bind.JAXBContext。
2. 实现类找到了TongWeb自带的 com.tongweb.persistence.jaxb.JAXBContextFactory 导致解析xml文件出错。因为tongweb-jaxb.jar/META-INF/services目录下有这个配置,所以优先加载了。
3. 应用采用JDK17,而JDK17中没有com.sun.xml.internal.bind.v2.ContextFactory这个类了,所以要从应用中找实现类。
由此可以判断应用中带有javax.xml.bind.JAXBContext的实现类,查找jaxb相关jar,可以找到相关配置,用的org.glassfish.jaxb.runtime.v2.ContextFactory

#第三方开源
-Djakarta.xml.bind.JAXBContext=com.sun.xml.bind.v2.ContextFactory
-Djakarta.xml.bind.JAXBContext=org.glassfish.jaxb.runtime.v2.ContextFactory
#JDK自带,JDK11后不带
-Djakarta.xml.bind.JAXBContext=com.sun.xml.internal.bind.v2.ContextFactory
案例2:
hibernate处理validation.xml报错如下:
Caused by: jakarta.validation.ValidationException: HV000100: Unable to parse META-INF/validation.xml.
at org.hibernate.validator.internal.xml.config.ValidationXmlParser.parseValidationXml(ValidationXmlParser.java:102)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.getBootstrapConfiguration(AbstractConfigurationImpl.java:514)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.parseValidationXml(AbstractConfigurationImpl.java:709)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.buildValidatorFactory(AbstractConfigurationImpl.java:423)
at jakarta.validation.Validation.buildDefaultValidatorFactory(Validation.java:103)
at org.hibernate.boot.beanvalidation.TypeSafeActivator.getValidatorFactory(TypeSafeActivator.java:511)
... 88 more
Caused by: org.xml.sax.SAXParseException: cvc-elt.1.a: Cannot find the declaration of element 'validation-config'.
at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204)
at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:135)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:396)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:284)
at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2133)
at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:830)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:615)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3079)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:836)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:114)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:542)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:889)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:825)
at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.StreamValidatorHelper.validate(StreamValidatorHelper.java:178)
at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:115)
at java.xml/javax.xml.validation.Validator.validate(Validator.java:124)
at org.hibernate.validator.internal.xml.config.ValidationXmlParser.parseValidationXml(ValidationXmlParser.java:88)
... 93 more
可以调整的参数如下:
# 应用中有xercesImpl.jar
-Djavax.xml.validation.SchemaFactory=org.apache.xerces.jaxp.validation.ValidatorImpl
#JDK默认实现类
-Djavax.xml.validation.SchemaFactory=com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl
重点说明:有时因为应用jar包过多,不确定默认值采用的哪一个,可以参考如下servlet代码在应用中运行遍历类路径下services目录下的默认值和-D值。
package com.tong;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@WebServlet("/scan-services")
public class ServicesScannerServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.println("<html>");
out.println("<head><meta charset=UTF-8></head>");
out.println("<body style='padding:20px;font-family:Arial'>");
out.println("<h2>所有 Jar 中 META-INF/services/ 下的全部文件</h2><hr>");
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> urls = loader.getResources("META-INF/services/");
int index = 1;
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
String protocol = url.getProtocol();
if ("jar".equals(protocol)) {
// ===== 处理 Jar 文件 =====
String jarPath = ((JarURLConnection) url.openConnection()).getJarFile().getName();
String jarName = new File(jarPath).getName();
try (JarFile jarFile = new JarFile(jarPath)) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 只匹配 META-INF/services/ 下的文件(不是目录)
if (name.startsWith("META-INF/services/") && !entry.isDirectory()) {
String fileName = name.substring("META-INF/services/".length());
out.println("<div style='border:1px solid #ccc;margin:10px 0;padding:12px;'>");
out.println("<div><b>" + (index++) + "、</b></div>");
out.println("<div>Jar 包:" + jarPath + "</div>");
out.println("<div>文件:" + fileName + " ,对应-D参数检查:"+System.getProperty(fileName)+"</div>");
out.println("<div>内容:</div>");
out.println("<pre style='background:#f8f8f8;padding:8px;'>");
// 读取内容
try (InputStream is = jarFile.getInputStream(entry);
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
String line;
int lineNum = 1;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.isEmpty() || line.startsWith("#")) continue;
out.println(lineNum++ + ": " + line);
}
}
out.println("</pre>");
out.println("</div>");
}
}
}
}
}
out.println("<hr>扫描完成");
out.println("</body></html>");
}
}
输出如下:

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)