我在同一Tomcat上运行的两次独立 war 中使用Amazon S3 SDK。我在我的Spring服务之一的@PostConstruct中初始化了AmazonS3Client。

如果我分别进行这些 war ,通常一切正常。如果我一起运行它们,则其中一个-第二个要启动-抛出以下异常:



我有一个解决方法,如果发生这种情况,在捕获AmazonClientException之后,我将设置以下System属性:

try {
  init();
} catch (AmazonClientException ase) {
  System.setProperty("org.xml.sax.driver", "com.sun.org.apache.xerces.internal.parsers.SAXParser");
  init();
}

但这当然是可怕的。有一个更好的方法吗?为什么在这种情况下会发生这种情况?

更新:起初,似乎将AmazonS3Client的初始化从@PostConstruct移出并对其进行了初始化,从而完全避免了此错误。但是显然它有时仍然会发生-即使我只打一场而不是打两次。

最佳答案

XMLReader通过一系列步骤来确定要使用的驱动器。引用文档

  • 如果系统属性org.xml.sax.driver具有值,则使用该值
    作为XMLReader类名。
  • JAR“服务API”用于查看
    的META-INF/services/org.xml.sax.driver文件中的类名称
    jarfiles可用于运行时。
  • SAX解析器分发是
    强烈建议您提供一个默认的XMLReader类名称,该名称应
    仅当先前选项(在此列表中)没有时才会生效
    成功的。
  • 最后,如果ParserFactory.makeParser()可以返回一个
    系统默认的SAX1解析器,该解析器包装在
    ParserAdapter。 (这是针对SAX1环境的迁移辅助工具,其中
    org.xml.sax.parser系统属性通常可以使用。)

  • 查看AWS SDK的代码...
    public XmlResponsesSaxParser() throws AmazonClientException {
        // Ensure we can load the XML Reader.
        try {
            xr = XMLReaderFactory.createXMLReader();
        } catch (SAXException e) {
            // oops, lets try doing this (needed in 1.4)
            System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
            try {
                // Try once more...
                xr = XMLReaderFactory.createXMLReader();
            } catch (SAXException e2) {
                throw new AmazonClientException("Couldn't initialize a sax driver for the XMLReader");
            }
        }
    }
    

    关于该代码,我有几件我不喜欢的事情。
  • 吞噬了SaxException e的根本原因。
  • SaxException e2的根本原因也被吃光了。该代码至少应该做的是打印一条警告,指出根本原因。
  • 在级别框架代码中使用System.setProperty()可能会导致一些难以调试的问题。

  • 这些要点使调试问题变得更加困难。我能做出的最有根据的猜测是,深红色解析器可在一个类加载路径中访问,而在另一个类加载路径中不存在。解决问题的一种 final方法是在代码上设置一个断点,以尝试实例化读取器并找出根本原因。

    关于java - 最佳实践: Creation of SAX parser for XMLReader,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12180606/

    10-10 05:52