4

我正在构建一个使用磁贴的 Struts2 Web 应用程序,但是我发现了一个非常令人沮丧的问题,如果 apache.org 关闭(这似乎经常发生),Web 应用程序将无法启动。这是因为在其标准设置中,StrutsTilesListener 会尝试加载包含 DOCTYPE 的切片定义文件,该文件具有指向位于 tiles.apache.org 上的 DTD 的 public-id。

当应用程序启动时,定义文件是通过 Apache Commons Digester 使用 Apache Xerces 加载的,它尝试从 tiles.apache.org 加载 DTD,但是如果 apache.org 关闭,那么这将失败并且整个 Web 应用程序将无法启动。

我可以通过下载文件并将其放置在本地并在struts定义文件中指定新的本地位置来绕过远程位置的下载,但是此解决方案不是很便携,因为本地保存DTD的位置可能不同开发人员机器和不同的一旦上传到实时环境,所以我将不得不继续编辑位置,以便适合运行 webapp 的机器,这简直是烦人的。

项目中没有其他 xml 文件有这个问题,包括 struts.xml 文件,它在 apache.org 上也有一个 DTD 位置,因此很明显存在一个设置问题,其中 Tiles 严格要求 DTD,但其他组件不是。有什么解决办法吗?我已经没有耐心了,我无法让这个 webapp 上线,因为我知道如果 apache.org 在我重新启动它时关闭,webapp 将不会重新启动。

Struts tile 定义文件

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
    <definition name="master" template="/tiles/templates/master.jsp">
    </definition>
    <definition name="public" extends="master">
        <put-attribute name="header" value="/tiles/templates/public/header.jsp" />
        <put-attribute name="footer" value="/tiles/templates/public/footer.jsp" />
        <put-attribute name="templateMeta" value="/tiles/templates/public/meta.jsp" />
    </definition>  
</tiles-definitions>

apache.org 关闭时的堆栈跟踪

SEVERE: Exception sending context initialized event to listener instance of class org.apache.struts2.tiles.StrutsTilesListener
java.lang.IllegalStateException: Unable to instantiate container.
    at org.apache.tiles.web.startup.TilesListener.contextInitialized(TilesListener.java:60)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3972)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4467)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
    at org.apache.catalina.core.StandardService.start(StandardService.java:519)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Caused by: org.apache.tiles.definition.DefinitionsFactoryException: I/O Error reading definitions.
    at org.apache.tiles.definition.digester.DigesterDefinitionsReader.read(DigesterDefinitionsReader.java:273)
    at org.apache.tiles.definition.UrlDefinitionsFactory.readDefinitions(UrlDefinitionsFactory.java:286)
    at org.apache.tiles.definition.UrlDefinitionsFactory.init(UrlDefinitionsFactory.java:130)
    at org.apache.tiles.impl.BasicTilesContainer.initializeDefinitionsFactory(BasicTilesContainer.java:406)
    at org.apache.tiles.impl.BasicTilesContainer.init(BasicTilesContainer.java:130)
    at org.apache.tiles.factory.TilesContainerFactory.initializeContainer(TilesContainerFactory.java:232)
    at org.apache.tiles.factory.TilesContainerFactory.createTilesContainer(TilesContainerFactory.java:198)
    at org.apache.tiles.factory.TilesContainerFactory.createContainer(TilesContainerFactory.java:163)
    at org.apache.tiles.web.startup.TilesListener.createContainer(TilesListener.java:90)
    at org.apache.struts2.tiles.StrutsTilesListener.createContainer(StrutsTilesListener.java:68)
    at org.apache.tiles.web.startup.TilesListener.contextInitialized(TilesListener.java:57)
    ... 15 more
Caused by: java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at org.apache.commons.digester.Digester.createInputSourceFromURL(Digester.java:2072)
    at org.apache.commons.digester.Digester.resolveEntity(Digester.java:1725)
    at com.sun.org.apache.xerces.internal.util.EntityResolverWrapper.resolveEntity(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.resolveEntityAsPerStax(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at org.apache.commons.digester.Digester.parse(Digester.java:1887)
    at org.apache.tiles.definition.digester.DigesterDefinitionsReader.read(DigesterDefinitionsReader.java:267)
    ... 25 more
4

3 回答 3

16

我发现了问题,这是我的错,我在问题中所说的一切都是真的,但这只是因为在tiles.xml文件中声明的DTD版本与我使用的瓷砖版本不匹配.

我实际上使用的是 Tiles 2.0.6,但是从 tile 2.1 中引用了 DTD,因此,tile 没有引用捆绑的 DTD,而是尝试下载它。

<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">

本来应该

<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
于 2011-03-03T08:40:43.820 回答
3

我得到了一个类似的异常,其根本原因如下 -

Caused by: org.apache.tiles.definition.DefinitionsFactoryException: I/O Error reading definitions.
at org.apache.tiles.definition.digester.DigesterDefinitionsReader.read(DigesterDefinitionsReader.java:273)
at org.apache.tiles.definition.UrlDefinitionsFactory.readDefinitions(UrlDefinitionsFactory.java:286)

我正在使用 Apache Tile 3.0。

解决方案:

我下载了文件“tiles-config_3_0.dtd”并将其放在 WEB-INF/dtd 目录中。在 tiles-definition.xml 文件中进行了以下更改 -

<!DOCTYPE tiles-definitions PUBLIC
   "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
   "jndi:/localhost/myapp/WEB-INF/dtd/tiles-config_3_0.dtd">

它工作正常,此后不再查找文件的绝对路径。

于 2014-04-24T05:38:45.607 回答
0

您可以获取 dtd 并将其放置在您的应用程序中。然后更改 URL 以引用您的本地副本。

只需执行“wget”或在浏览器中查看它并将文件保存到您的项目中。

于 2011-03-02T17:14:52.553 回答