Topics in This Chapter
In any programming language, the ability to iterate over a set of values is essential. Before JSTL, JSP did not provide an explicit means to accomplish that fundamental task, so developers had two choices: use a scriptlet or implement a custom action, neither of which is very attractive. JSTL provides two actions that iterate over a set of values: <c:forEach> and <c:forTokens>. JSTL also exposes an interface and two classes that you can use to implement custom iteration actions: LoopTag , LoopTagSupport , and LoopTagStatus , respectively. [1] This chapter describes the <c:forEach> and <c:forTokens> actions and shows you how to implement custom actions using the LoopTag interface and the LoopTagSupport and LoopStatus classes.
To iterate over a set of values with a scriptlet, you must be proficient in the Java programming language and you must also understand how Java and HTML interact within JSP pages. For example, consider the following code fragment: <% int[] values = (int[])request.getAttribute("primitiveValues"); for(int i=0; i < values.length; ++i) { %> value = <%= values[i] %><br> <% } %> The preceding scriptlet iterates over an array of int s stored in request scope. That scriptlet is short, but it requires you to be familiar with the following constructs:
Even for seasoned Java developers, it's not uncommon to forget the required cast in the preceding code fragment. If you are a page author and you're not familiar with the constructs listed above, or if you're a veteran Java developer and you want to avoid scriptlets, the JSTL iteration actions are for you. Consider the simplicity of the following code fragment, which is functionally identical to the preceding scriptlet: <c:forEach items='${primitiveValues}' var='item'> value = <c:out value='${item}'/><br> </c:forEach> The preceding code fragment uses the <c:forEach> action to iterate over the same array that the scriptlet accesses . Although that code is not much shorter than its scriptlet counterpart , it's much simpler because none of the constructs listed above are required. In the preceding code fragment, two of the <c:forEach> action's attributes are specified: items and var ; the former specifies the set of values that <c:forEach> iterates over, and the latter specifies the name of a scoped variable that references the current item of the iteration. The var scoped variable is only available within the body of the <c:forEach> action. Not only does <c:forEach> simplify iteration, it also lets you iterate over many different types of data structures. Also, no matter what type of data you iterate over, the code that you write will be nearly identical to the preceding code fragment. The only difference is the value of the <c:forEach> items attribute. [2]
Figure 4-1 shows a JSP page that contains both of the preceding code fragments . Figure 4-1. Looping Over Primitive Types with a Scriptlet vs. Looping with JSTL
The JSP page shown in Figure 4-1 is listed in Listing 4.1. Perhaps the most difficult aspect of iterating with JSTL actions is that you must remember to specify the taglib directive for the JSTL core actions. If you forget that declaration, the <c:forEach> and <c:forTokens> actions will do nothing. [3]
Listing 4.1 Looping with a Scriptlet vs. Using JSTL<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Looping Over Primitive Values</title> </head> <body> <%-- The taglib directive for the JSTL core actions --%> <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%-- Create an array of ints and store them in request scope --%> <% int[] primitiveValues = {1,2,3,4,5,6,7,8,9,10}; pageContext.setAttribute("primitiveValues", primitiveValues, PageContext.REQUEST_SCOPE); %> <%-- Loop over the array and print its values using a scriptlet --%> Looping Over Arrays of Primitive Types With a Scriptlet:<p> <% int[] values = (int[])request.getAttribute( "primitiveValues"); for(int i=0; i < values.length; ++i) { %> value = <%= values[i] %><br> <% } %> <p> <%-- Loop over the array and print its values using JSTL's <c:forEach> action --%> Looping Over Arrays of Primitive Types with JSTL:<p> <c:forEach items='${primitiveValues}' var='item'> value = <c:out value='${item}'/><br> </c:forEach> </body> </html> |