为什么Tiles REGEXP通配符定义导致无限的jsp包括错误

时间:2011-06-29 13:43:00

标签: struts2 tiles2

我使用了Struts2 2.2.3的tile 2.2.2,因为Struts2-Tiles插件已经很老了,它的实现使用了很多Tiles弃用的API,我想尝试使用REGEXP通配符,所以我在下面实现了我自己的监听器:

MyTilesContainerFactory

package tiles;

import org.apache.tiles.definition.pattern.DefinitionPatternMatcherFactory;
import org.apache.tiles.definition.pattern.PatternDefinitionResolver;
import org.apache.tiles.definition.pattern.PrefixedPatternDefinitionResolver;
import org.apache.tiles.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory;
import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory;
import org.apache.tiles.factory.BasicTilesContainerFactory;


public class MyTilesContainerFactory extends BasicTilesContainerFactory {

  @Override
  protected <T> PatternDefinitionResolver<T> createPatternDefinitionResolver(Class<T> customizationKeyClass) {

    DefinitionPatternMatcherFactory wildcardFactory = new WildcardDefinitionPatternMatcherFactory();
    DefinitionPatternMatcherFactory regexpFactory = new RegexpDefinitionPatternMatcherFactory();
    PrefixedPatternDefinitionResolver<T> resolver = new PrefixedPatternDefinitionResolver<T>();
    resolver.registerDefinitionPatternMatcherFactory("WILDCARD", wildcardFactory);
    resolver.registerDefinitionPatternMatcherFactory("REGEXP", regexpFactory);
    return resolver;
  }
}

MyTilesInitializer

package tiles;

import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.factory.AbstractTilesContainerFactory;
import org.apache.tiles.startup.AbstractTilesInitializer;


public class MyTilesInitializer extends AbstractTilesInitializer {

  @Override
  protected AbstractTilesContainerFactory createContainerFactory(TilesApplicationContext context) {
    return new MyTilesContainerFactory();
  }

}

MyTilesListener

package tiles;

import org.apache.tiles.startup.TilesInitializer;
import org.apache.tiles.web.startup.AbstractTilesListener;


public class MyTilesListener extends AbstractTilesListener {

  @Override
  protected TilesInitializer createTilesInitializer() {
    return new MyTilesInitializer();
  }


}

然后我定义了tiles.xml

<tiles-definitions>
  <definition name="REGEXP:(.*)" template="/WEB-INF/tiles/basicLayout.jsp">
    <put-attribute name="header" value="/WEB-INF/tiles/header.jsp" />
    <put-attribute name="content" value="/WEB-INF/pages/{1}.jsp" />
    <put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp" />
  </definition>
</tiles-definitions>

当我尝试一个返回tile结果的动作时,它会以无限循环结束,jsp包含错误。

SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.StackOverflowError
    at java.io.UnixFileSystem.getBooleanAttributes0(Native Method)
    at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:228)
    at java.io.File.exists(File.java:733)
    at sun.misc.URLClassPath$FileLoader.getResource(URLClassPath.java:999)
    at sun.misc.URLClassPath.getResource(URLClassPath.java:169)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    at org.apache.jasper.compiler.ErrorDispatcher.createJavacError(ErrorDispatcher.java:526)
    at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:490)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:416)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
    at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:535)
    at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:472)
    at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:968)
    at org.apache.jasper.runtime.PageContextImpl.doInclude(PageContextImpl.java:638)
    at org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:632)
    at org.apache.tiles.jsp.context.JspTilesRequestContext.include(JspTilesRequestContext.java:103)
    at org.apache.tiles.jsp.context.JspTilesRequestContext.dispatch(JspTilesRequestContext.java:96)
    at org.apache.tiles.renderer.impl.TemplateAttributeRenderer.write(TemplateAttributeRenderer.java:44)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:690)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:644)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:627)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
    at org.apache.tiles.renderer.impl.DefinitionAttributeRenderer.write(DefinitionAttributeRenderer.java:56)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.renderer.impl.ChainedDelegateAttributeRenderer.write(ChainedDelegateAttributeRenderer.java:76)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:336)
    at org.apache.tiles.template.InsertAttributeModel.renderAttribute(InsertAttributeModel.java:210)
    at org.apache.tiles.template.InsertAttributeModel.end(InsertAttributeModel.java:126)
    at org.apache.tiles.jsp.taglib.InsertAttributeTag.doTag(InsertAttributeTag.java:311)
    at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspx_meth_tiles_005finsertAttribute_005f0(basicLayout_jsp.java:128)
    at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspService(basicLayout_jsp.java:93)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
    at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:535)
    at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:472)
    at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:968)
    at org.apache.jasper.runtime.PageContextImpl.doInclude(PageContextImpl.java:638)
    at org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:632)
    at org.apache.tiles.jsp.context.JspTilesRequestContext.include(JspTilesRequestContext.java:103)
    at org.apache.tiles.jsp.context.JspTilesRequestContext.dispatch(JspTilesRequestContext.java:96)
    at org.apache.tiles.renderer.impl.TemplateAttributeRenderer.write(TemplateAttributeRenderer.java:44)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:690)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:644)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:627)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
    at org.apache.tiles.renderer.impl.DefinitionAttributeRenderer.write(DefinitionAttributeRenderer.java:56)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.renderer.impl.ChainedDelegateAttributeRenderer.write(ChainedDelegateAttributeRenderer.java:76)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:336)
    at org.apache.tiles.template.InsertAttributeModel.renderAttribute(InsertAttributeModel.java:210)
    at org.apache.tiles.template.InsertAttributeModel.end(InsertAttributeModel.java:126)
    at org.apache.tiles.jsp.taglib.InsertAttributeTag.doTag(InsertAttributeTag.java:311)
    at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspx_meth_tiles_005finsertAttribute_005f0(basicLayout_jsp.java:128)
    at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspService(basicLayout_jsp.java:93)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

有人可以给我建议吗?我不得不说,如果我不使用通配符定义,相同的定义工作正常。非常感谢。

1 个答案:

答案 0 :(得分:4)

我对此并不是很满意,但我希望它有所帮助。您正在使用的正则表达式可能是您可能使用的最贪婪的表达式。它匹配所有内容,这包括tile定义本身内的所有内容(basicLayout.jsp,header.jsp,footer.jsp)。这解释了为什么您获得无限循环,因为您的REGEXP切片定义会保持匹配每个文件请求并尝试使用新模板调用(模板递归!)来满足每个新文件请求。

Tiles Wildcard support page显示了几个例子。这些例子都没有使用(。*) - 我想我们刚刚解决了为什么会这样。

你需要让你的REGEXP稍微贪婪;我知道Struts使用稍微不同的方法来调用模板块,但想象一下你有一个JSP页面包含:

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insertDefinition name="somepage.tile" />

并且以下切片定义应创建包含 /WEB-INF/pages/somepage.jsp 内容的模板页面:

<definition name="REGEXP:(.*)\.tile" template="/WEB-INF/tiles/basicLayout.jsp">
  <put-attribute name="header" value="/WEB-INF/tiles/header.jsp" />
  <put-attribute name="content" value="/WEB-INF/pages/{1}.jsp" />
  <put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp" />
</definition>