根据静态块中给定的 xsd 与非静态块验证 xml

问题描述 投票:0回答:1

我有两种方法根据存储在旧应用程序资源中的 xsd 验证 xml。每天验证 1000 多次,代码 24*7 运行。

方法一: 就是创建静态SchemaFactory

public class XmlValidator {
    private static final SchemaFactory schemaFactory;
    
    static {
        schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI, "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", ClassLoader.getSystemClassLoader()); // This is done because of conflict due to xerces from //external jar and from Java
        schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
        schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
    }
    
    public boolean validateXmlWithXsd(String inputXml, String xsd) {
        try (InputStream stream = new ByteArrayInputStream(xsd.getBytes(StandardCharsets.UTF_8));
             StringReader reader = new StringReader(inputXml)) {
            
            Source schemaFile = new StreamSource(stream);
            Schema schema = schemaFactory.newSchema(schemaFile);
            
            Validator validator = schema.newValidator();
            validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
            
            Source source = new StreamSource(reader);
            validator.validate(source);
            
            return true; // Validation successful
        } catch (Exception e) {
            // Handle validation errors here
            e.printStackTrace();
            return false; // Validation failed
        }
    }
}

方法2:(只需更改方法validateXmlWithXsd,无需静态块)

public boolean validateXmlWithXsd (String inputXml, String xsd) {
try{
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI, "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory", ClassLoader.getSystemClassLoader())
InputStream stream = new ByteArrayInputStream (xsd.getBytes(StandardCharsets.UTF_8));
Source schemaFile = new StreamSource(stream);


Schema schema = schemaFactory.newSchema(schemaFile);
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
Validator validator = schema. newValidator();
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
Source source = new StreamSource(new StringReader (inputXml)):
validator.validate(source);
}
}

我的想法: 使用系统类加载器调用 SchemaFactory.newInstance,尤其是在长时间运行的线程中重复调用时(在 24*7 场景中重复调用 1000 次以上),可能会导致性能问题,并且可能不是最有效的方法。主要是由于类加载开销。所以,我更喜欢方法 1。另外,对于静态 SchemaFactory,我认为它有助于记忆:

单实例:当我声明一个静态 SchemaFactory 时,只有一个实例在类的所有实例之间共享。这意味着仅创建 SchemaFactory 一次,所有后续对 XML 验证方法的调用都使用同一个工厂。

资源共享:SchemaFactory创建起来比较繁重,可以配置各种属性。通过使其静态,我们可以避免每次需要验证 XML 时重新创建它。这可以节省内存和 CPU 周期。

方法2:如果我们在validateXmlWithXsd()方法中创建SchemaFactory,那么一旦该方法退出,它就会有资格进行垃圾回收,并且该实例占用的内存可能会被释放。因此,这种方法可能不会造成严重的内存问题。

任何人都可以建议方法1相对于方法2是否有任何缺点。

java xml xml-parsing xxe
1个回答
0
投票

SchemaFactory
的文档说它不是线程安全的:

SchemaFactory 类不是线程安全的。换句话说,应用程序有责任确保在任何给定时刻最多有一个线程正在使用 SchemaFactory 对象。

如果可以从多个线程调用

validateXmlWithXsd
,则必须使用同步块或其他锁定机制来确保不会并发使用
schemaFactory
。这可能会造成其自身的性能瓶颈。

© www.soinside.com 2019 - 2024. All rights reserved.