问题
Is there a way to create a while loop like structure with JSP, without using a scriptlet?
I ask as I have a linked list-like structure (specifically, printing the cause chain for exceptions) which AFAIK does not have an iterator interface to use forEach on.
回答1:
You could do it by iterating over a list
<c:forEach var="entry" items="${requestScope['myErrorList']}">
${entry.message}<br/>
</c:forEach>
EDIT:
You could have a method like the following to transform an exception and its causes into list that later could be shown using a forEach
public static List<Throwable> getExceptionList(Exception ex) {
List<Throwable> causeList = new ArrayList<Throwable>();
causeList.add(ex);
Throwable cause = null;
while ((cause = ex.getCause()) != null && !causeList.contains(cause)) {
causeList.add(cause);
}
return causeList;
}
For example:
try {
...
} catch (... ex) {
request.setAttribute("myErrorList", getExceptionList(ex));
}
回答2:
The controller, whose role is to prepare the data for the view, should transform this non-iterable data structure into a collection that can be used by the <c:forEach>
JSTL tag.
回答3:
What I ended up doing was a static loop with an arbitrary upper bound:
<c:forEach begin="0" end="${<upper_bound>}" varStatus="loop">
<c:if test="${!<exit_condition>}">
<!-- loop output here -->
</c:if>
<c:if test="${loop.last && !<exit_condition>}">
<!-- overflow output here -->
</c:if>
</c:forEach>
This is really only useful only if you have some prior knowledge of the number of iterations, don't mind not displaying all information, or don't mind a potentially significant performance hit.
Keep in mind there is no early exit condition, so putting 2,147,483,647 as an upper bound would be a decidedly bad idea.
And for the curious, solution for outputting exceptions (sans formatting):
<c:forEach begin="0" end="10" varStatus="loop">
<c:if test="${!loop.first}">
Caused By:
</c:if>
<c:if test="${throwable != null}">
Message: ${throwable.message} <br/>
<c:forEach items="${throwable.stackTrace}" var="trace">
${trace} <br/>
</c:forEach>
</c:if>
<c:if test="${loop.last && throwable != null}">
More causes not listed...
</c:if>
<c:set var="throwable" value="${throwable.cause}" />
</c:forEach>
回答4:
In case you don't want to iterate over Collections, you can use <c:forEach>
as a conventional loop equivalent by the following approach:
<c:set var="startIndex" scope="page" value="0"/>
<c:set var="endIndex" scope="page" value="12"/>
<select name="milestone_count" id="milestone_count">
<option value="">-select-</option>
<c:forEach begin="${startIndex}" end="${endIndex}" step="1" var="index">
<option value="${index}">${index}</option>
</c:forEach>
</select>
This will produce a select drop down ranging from 0 to 12
回答5:
http://www.tutorialspoint.com/jsp/jstl_core_foreach_tag.htm
<c:forEach var="item" items="${myList}">
${item}"
</c:forEach>
<c:forEach var="entry" items="${myMap}">
Key: <c:out value="${entry.key}"/>
Value: <c:out value="${entry.value}"/>
</c:forEach>
来源:https://stackoverflow.com/questions/17702459/jstl-while-loop-without-scriptlets