何时在JSP中设置请求范围的变量?

时间:2011-09-28 17:18:30

标签: jsp jstl scope lexical-scope dynamic-scope

根据我的经验,很少/根本不需要在EL变量上设置scope="request"

例如,我有一个页面,给定item参数,根据其属性构造特定于该项的URL。此页面包含在需要呈现项目链接的任何页面中。

(A)使用请求范围的变量

itemLink.jsp

<%-- Accepts a parameter named 'item' --%>
<c:set var="urlTemplate" value="${param['item'].urlTemplate}" />
<c:choose>
  <c:when test="${empty urlTemplate}">
    <c:set var="itemUrl" scope="request" value="/missingProductUrl.jsp"/>
  </c:when>
  <c:otherwise>
    <c:url var="itemUrl" scope="request" value="${urlTemplate}">
      <c:param name="id" value="${param['item'].id}"/>
    </c:url>
  </c:otherwise>
</c:choose>

otherPage.jsp

<jsp:include page="itemLink.jsp">
  <jsp:param name="item" value="${currentItem}"/>
</jsp:include>

<%-- 'itemUrl' has request scope --%>
<a href="${itemUrl}">Item Link</a>

(B)没有请求范围的变量

itemLink.jsp

<%-- Accepts a parameter named 'item' --%>
<c:set var="urlTemplate" value="${param['item'].urlTemplate}" />
<c:choose>
  <c:when test="${empty urlTemplate}">
    <c:set var="itemUrl" value="/missingProductUrl.jsp"/>
  </c:when>
  <c:otherwise>
    <c:url var="itemUrl" value="${urlTemplate}">
      <c:param name="id" value="${param['item'].id}"/>
    </c:url>
  </c:otherwise>
</c:choose>

<c:out value="${itemUrl}"/>

otherPage.jsp

<c:set var="itemUrl">
  <jsp:include page="itemLink.jsp">
    <jsp:param name="item" value="${currentItem}"/>
  </jsp:include>
</c:set>

<%-- 'itemUrl' has page scope --%>
<a href="${itemUrl}">Item Link</a>

有没有理由使用(A)而不是(B)?我的答案是否定的,理由如下:

  • 使用(A),您需要记住在同一请求中处理的任何其他网页都会看到itemUrl,因此您应该避免名称冲突。它还使得跟踪EL变量的来源变得更加困难,因为除了搜索在同一请求期间处理的所有页面之外,无法找到设置请求范围变量的位置。

  • 使用(B),这些都不是问题,因为变量只有页面范围。

修改

也许有比(B)

更好的解决方案

(C)使用静态包含

itemLink.jspf

<%-- Accepts a parameter named 'item' --%>
<c:set var="urlTemplate" value="${param['item'].urlTemplate}" />
<c:choose>
  <c:when test="${empty urlTemplate}">
    <c:set var="itemUrl" value="/missingProductUrl.jsp"/>
  </c:when>
  <c:otherwise>
    <c:url var="itemUrl" value="${urlTemplate}">
      <c:param name="id" value="${param['item'].id}"/>
    </c:url>
  </c:otherwise>
</c:choose>

otherPage.jsp

<c:set var="item" value="${currentItem}"/>
<%@ include page="itemLink.jsp" %>

<%-- 'itemUrl' has page scope --%>
<a href="${itemUrl}">Item Link</a>

仍然存在这样的情况:(B)(C)都不需要使用请求范围的变量。是否有一些理由使用我错过的请求范围?

1 个答案:

答案 0 :(得分:4)

您提交的这一部分


<c:set var="itemUrl">
<jsp:include page="itemLink.jsp">
<jsp:param name="item" value="${currentItem}"/>
</jsp:include>
</c:set>
只有当itemLink.jsp只有itemUrl的值而没有其他内容(没有额外的html内容)时,

才有效。但这种情况几乎不存在。

考虑一个情况,你的one.jsp中的请求范围中有一个Car对象,这个页面中的一个链接将你带到一个需要同一个Car对象的two.jsp。

然后


<c:set var="myCar" value="${requestScope.car}" scope="request"/> 

会做这个工作。用方法(B)这是不可能的。

<强>更新 至于为什么方法(B)不可能:在你的代码片段中,jsp:include包含JSP的响应(文本),然后设置为itemUrl。如果需要将复杂对象(非文本,如Car或ArrayList)分配给请求范围属性,该怎么办? JSP响应通常是 一个html文本。

只是提出一个替代方案,为什么不这样做呢?



<%-- Accepts a parameter named 'item' --%>
<c:set var="urlTemplate" value="${param['item'].urlTemplate}" />
<c:choose>
<c:when test="${empty urlTemplate}">
<a href value="/missingProductUrl.jsp"/>
</c:when>
<c:otherwise>
<c:url var="itemUrl" scope="request" value="${urlTemplate}">
<c:param name="id" value="${param['item'].id}"/>
</c:url>
<c:out value="${itemUrl}"/>
</c:otherwise>
</c:choose>



<jsp:include page="itemLink.jsp">
<jsp:param name="item" value="${currentItem}"/>
</jsp:include>

所有人都说,我几乎没有需要c:set的情况。通常,任何作用域属性的设置都由servlet / controller完成。 JSP只会获得一个scoped属性并显示它。如果JSP设置范围属性,则维护起来非常困难。最好将c:set的使用限制为仅设置页面范围属性。