增强的jsp:include实现

时间:2010-08-08 17:40:19

标签: java jsp

我一直困扰<jsp:include..>的一件事是,无法将非String值作为页面的不同输入传递到包含的页面中。例如,我希望能够做到以下几点:

<c:forEach var="item" items="${listOfItems}">
    <jsp:include page="mypage.jsp">
        <jsp:attribute name="item" value="${item}/>
    </jsp:include>
</c:forEach>

这个想法是,通过声明项目作为jsp:include节点内的属性传入,代码正在明确意图是什么......将该参数提供给包含的页面。

目前唯一可用的机制是定义属性“global”,然后让包含的页面从全局空间中读取它。不幸的是,这失去了使用&lt; jsp:param&gt;的相同“意图”。提供。此外,它使代码更难调试,原因与任何编程环境中的全局变量相同。

有没有人知道执行jsp:include函数的include机制的实现,但允许传入非String值?或者,如果没有,我会接受其他想法,保持意图和调试的简单目标。

作为旁注,我很乐意看到内置的“catch”机制,当包含的页面抛出错误时:

<abc:include page="mypage">
    <abc:param name="something" value="some string value"/>
    <abc:attribute name="somethingelse" value="${nonStringValue}"/>
    <abc:catch var="ex">
        The page failed, so the content it generated will not be sent to the output
        stream. Instead, we can collapse the part of the page that it's content
        would be... possibly putting a comment in the page with
        <!-- There was an exception generating this module: 
             <c:out value="${ex.getMessage}/>
          -->
    </abc:catch>
</abc:include>

4 个答案:

答案 0 :(得分:4)

来自JSTL规范:

  

嵌套范围变量仅在操作主体中可见并存储   在“页面”范围内。

您可以通过 request 范围传递对象引用。

standardInclude.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:out value="${foo}" />

standardAction.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
  //evil scriptlet
  request.setAttribute("mylist", java.util.Arrays.asList("bar", "baz"));
%>
<c:forEach items="${mylist}" var="foo">
    <c:set var="foo" scope="request" value="${foo}" />
    <jsp:include page="standardInclude.jsp" />
    <c:set var="foo" scope="request" value="${null}" />
</c:forEach>

您可以使用catch标记来捕获异常。

thrower.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:out value="OK: ${foo}" />
<%
  //evil scriptlet
  if ("bar".equals(request.getAttribute("foo")))
    throw new java.io.IOException("oops");
%>

catcher.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
  //evil scriptlet
  request.setAttribute("mylist", java.util.Arrays.asList("bar", "baz"));
%>
<c:forEach items="${mylist}" var="foo">
    <br />
    <c:set var="foo" scope="request" value="${foo}" />
    <c:catch var="ex">
        <jsp:include page="thrower.jsp" />
    </c:catch>
    <c:if test="${ex ne null}">
        <c:out value="Error for ${foo}" />
    </c:if>
    <c:set var="foo" scope="request" value="${null}" />
</c:forEach>

这将发出:

Error for bar 
OK: baz 

答案 1 :(得分:1)

  

允许传入非String   值?

当您被限制传递字符串时,常见的解决方案是序列化您的对象。

答案 2 :(得分:1)

在这里阅读了答案,再加上对这个问题的进一步研究,我想出了以下内容:

  • 您可以序列化对象,然后在包含的JSP中反序列化它们。不是这个的粉丝,因为它使代码更复杂(你传入的每个对象必须是可序列化的等)
  • 您可以使用taglib。不喜欢这个,因为我觉得他们扮演的角色不同于JSP包含文件
  • 您可以在请求范围定义变量,这将使它们可用于包含的JSP。不是很喜欢这个,因为它没有显示程序员的意图(将值传递给包含的页面,仅供它使用)。
  • 确实没有(我能找到)实现能够实现我正在寻找的东西,但它可能是通过自定义标签构建的。

我做了一些工作并将代码放在一起以实现我想要的,然后threw it up on sourceforge。它允许您以我描述的方式指定输入:

<inc:include page="normal.jsp">
    <inc:param name="param1" value="param1value" />
    <inc:param name="param2" value="param2value" />
    <inc:attrib name="attrib1" value="${attrib1value}" />
    <inc:attrib name="attrib2" value="${attrib2value}" />
    <inc:catch var="ex">
       This block was not rolled up because there wasn't an error. 
       Should never see this, but just in case, the exception was: ${ex.message}
    </inc:catch>
</inc:include>

它的唯一问题(此时)是我在包含页面之前将属性添加到请求范围,然后在之后删除它们(如果它们已经存在则重置它们)。相反,我想要做的是包装请求对象并覆盖属性方法以自动包含传入的值...我仍在努力。

答案 3 :(得分:0)

这可以通过jsp标记文件而不是包含来实现。有关详细信息,请参阅我在JSP Component Creation处对类似问题的回答。

相关问题