Conditional statements are essential for any programming language, but before JSTL, JSP did not provide an explicit means to express conditional statements. JSTL offers the following conditional actions:
JSTL supports two types of conditions: simple and mutually exclusive. Simple conditions perform an action if a test condition is true, whereas mutually exclusive conditions perform one of several actions depending upon the value of a test condition. Simple conditions are supported by the <c:if> action, and mutually exclusive conditions are supported by the <c:choose>, <c:when>, and <c:otherwise> actions; the <c:if> action is discussed below and the <c:choose>, <c:when>, and <c:otherwise> actions are discussed in "Mutually Exclusive Conditions" on page 132. Simple ConditionsYou can use the <c:if> action with the following syntax: [14]
<c:if test [var] [scope]> body content that's processed if the value of the test attribute is true </c:out> The test attribute, which is required, is a boolean expression that determines whether the body of the <c:if> action is evaluated. That attribute is an EL expression for the <c:if> action and a Java expression for the <c_rt:if> action. The optional var and scope attributes specify a scoped variable that stores the boolean result of the expression specified with the test attribute. The following code fragment uses <c:if> to test the existence of a non- null request parameter named name : <c:if test='${not empty param.name}'> <c:out value='${param.name}'/> </c:if> If the name request parameter exists and is not null , the preceding code fragment displays its value. You can also use the var and scope attributes like this: <c_rt:if var='zipTest' scope='request' test='<%= request.getHeader("accept-encoding"). indexOf("gzip") != -1%>'> GZIP is supported </c_rt:if> The preceding code fragment uses the <c_rt:if> action to see if the current HTTP requests supports GZIP encoding; if so, the message GZIP is supported is displayed. The <c_rt:if> action in the preceding code fragment also stores the result of the test condition in a request-scoped variable named zipTest . Later on, for the same request and presumably in a different JSP page, you can test to see whether the current request supports the GZIP encoding, like this: <c:if test='${zipTest}'> GZIP is supported </c:if> The preceding code fragment uses <c:if> to test the value of the zipTest scoped variable; if that variable is true , the body of the <c:if> action is evaluated. Most of the time, if you store the result of a test condition in a scoped variable, as is the case for the preceding code fragment, you don't need a body for the <c:if> or <c_rt:if> action that creates the scoped variable. JSTL supports that use case with the following syntax: <c:if test var [scope]/> In the preceding code fragment, if you don't need to display a message if the GZIP encoding is supported for a particular request but you want to store a boolean variable that you can test against later, you can do this: <c_rt:if var='zipTest' scope='request' test='<%= request.getHeader("accept-encoding"). indexOf("gzip") != -1%>'/> The <c:if> action and its corresponding <c_rt:if> action are easy to understand and use, as the preceding code fragments illustrate . One popular use for the <c:if> action is to retain values for HTML option elements, which is discussed in the next section. Retaining Values for HTML Option ElementsIn "Retaining Values for HTML Text Elements" on page 106, we saw how to retain values for HTML text elements with the <c:out> action. In this section we explore how to retain values for HTML option elements with the <c:if> action. The JSP page shown in Figure 3-8 contains a form with two textfields and an HTML select element, which is populated with HTML option elements. The action for that form is unspecified, so when you activate the submit button, the JSP page is reloaded. As you can see from Figure 3-8, the textfields and the select element all retain their values when the JSP page is reloaded. The top picture in Figure 3-8 shows the JSP page when it's first loaded and a user has filled out the form, and the bottom picture shows the JSP page after the user has activated the submit button and the page has been reloaded. Figure 3-8. Retaining Values for HTML Option Elements with <c:if>
The JSP page shown in Figure 3-8 is listed in Listing 3.12. Listing 3.12 Retaining HTML Option Values<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Retain HTML Option Values</title> </head> <body> <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%-- Because the following form has no action, this JSP page will be reloaded when the form is submitted --%> <form> <table> <tr> <td>First Name:</td> <td><input type='text' name='firstName' value='<c:out value="${param.firstName}"/>'/> </td> </tr> <tr> <td>Last Name:</td> <td><input type='text' name='lastName' value='<c:out value="${param.lastName}"/>'/> </td> </tr> <tr> <td>Enter your credit card type:</td> <td> <%-- Create the HTML select element for credit card type --%> <select name='cardType'> <%-- Create option elements and select the previously selected credit card type --%> <option value='Visa' <c:if test='${param.cardType == "Visa"}'> selected </c:if> >Visa</option> <option value='MasterCard' <c:if test='${param.cardType == "MasterCard"}'> selected </c:if> >MasterCard</option> <option value='Discover' <c:if test='${param.cardType == "Discover"}'> selected </c:if> >Discover</option> </select> </td> </tr> </table> <p><input type='submit' value='Submit form'/> </form> </body> </html> The preceding JSP page retains values for its textfields with the <c:out> action and retains values for its option elements with the <c:if> action. Each option element is declared in three stages, like this: <select name='cardType'> ... <option value='Visa' <c:if test='${param.cardType == "Visa"}'> selected </c:if> >Visa</option> ... </select> First, the start tag for the option element is specified without the closing angle bracket . Second, if the cardType request parameter is the same as the name of the current option, the string selected is added to the option start tag. Third, the start tag is completed with the closing angle bracket, the display value is specified, and the option end tag is added. For the preceding code fragment, if Visa was the last card type selected, the following will be generated: <option value='Visa' selected>Visa</option> If the last card type selected was not Visa, the following will be generated: <option value='Visa'>Visa</option> The <c:if> action is handy for simple conditions, but it will not suffice for mutually exclusive actions, such as if/else or switch constructs. The following section shows you how to specify those constructs. Mutually Exclusive ConditionsSometimes you need to execute code if one of several conditions is true. This section shows you how to do that with the <c:choose>, <c:when>, and <c:otherwise> actions. When you specify a mutually exclusive condition with JSTL, the <c:choose> action is always the outermost action; the syntax for that action looks like this: [15]
<c:choose> body content that can only consist of one or more <c:when> actions followed by an optional <c:otherwise> action </c:choose> The body content of <c:choose> actions can only contain one or more <c:when> actions and, optionally , one <c:otherwise> action. The <c:otherwise> action, if specified, must be the last action in the body of the <c:choose> action. The <c:when> action has the following syntax: [16]
<c:when test> body content that ' s evaluated if this is the first <c:when> contained in a <c:choose> whose test evaluates to true </c:choose> The <c:when> action is similar to the <c:if> action ”both actions have a test attribute that determines whether the action's body content is evaluated. Unlike the <c:if> action, <c:when> actions do not have var and scope attributes, so you cannot store the result of a <c:when> action's boolean test in a scoped variable. The <c:otherwise> action's body content is evaluated only if none of the preceding <c:when> actions nested in the same <c:choose> action evaluated to true. Here is the syntax for the <c:otherwise> action: [17]
<c:otherwise> body content that ' s evaluated if none of the preceding <c:when> actions evaluated to true </c:otherwise> You can use the <c:choose>, <c:when>, and <c:otherwise> actions together to emulate if/else constructs or switch statements. The former is discussed in the next section and the latter is discussed in "Implementing Switch Statement Constructs" on page 136. Implementing If/Else ConstructsAn if/else statement is implemented with <c:choose>, <c:when>, and <c:otherwise> actions like this: <c:choose> <%-- The <c:when> action represents the if clause --%> <c:when test=' boolean expression '> <%-- Do something if the preceding test condition is true --%> </c:when> <%-- The <c:otherwise> action represents the else clause --%> <c:otherwise> <%-- Do something if the <c:when> condition is false --%> </c:otherwise> </c:choose> In the preceding code fragment, the <c:when> action represents the if clause and the <c:otherwise> action represents the else clause. Let's see how to put that construct to use with a JSP page ”shown in Figure 3-9 ”that simulates rolling dice. Figure 3-9. Rolling the Dice
When you activate the Roll the dice button in the JSP page shown in Figure 3-9, a random number is generated from 0 to 6, inclusive. If that number is greater than 0, the JSP page displays a die with the corresponding number. If that number is 0, the JSP page displays a message indicating that the roll was invalid. The top picture shown in Figure 3-9 shows a valid roll and the bottom picture depicts an invalid roll. The JSP page shown in Figure 3-9 is listed in Listing 3.13. The preceding JSP page uses the <c_rt:set> action to store a random number between 0 and 6 inclusive in a page-scoped variable named roll . Subsequently, an if/else construct is implemented with a single <c:when> action and a single <c:otherwise> action nested in a <c:choose> action. The <c:when> action tests the value stored in the roll scoped variable. If that variable contains a valid number for a dice roll, the body of the <c:when> action displays an image. The name of that image is constructed with the roll scoped variable with this EL expression: dice-${roll}.jpg . If the value stored in the roll scoped variable is 1, the image dice-1.jpg will be displayed; if the value is 2, the image dice-2.jpg will be displayed, and so on. If the roll scoped variable does not contain a valid number for a dice roll, the <c:otherwise> action displays a message that indicates an invalid roll. Listing 3.13 Emulating the If/Else Construct<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Emulate an If/Then/Else Construct</title> </head> <body> <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%@ taglib uri='http://java.sun.com/jstl/core_rt' prefix='c_rt' %> <%-- Roll the dice --%> <c_rt:set var='roll'> <%= (int)(Math.random() * 7) %> </c_rt:set> <%-- Emulate an if/then construct --%> <c:choose> <%-- If it was a good roll --%> <c:when test='${roll >= 1 && roll <= 6}'> <img src='<c:out value=" dice-${roll}.jpg "/>'> </c:when> <%-- If it was a bad roll --%> <c:otherwise> Oops, the dice rolled off the table! Try again. </c:otherwise> </c:choose> <%-- Because the following form has no action, this JSP page will be reloaded when the form is submitted --%> <form> <input type='submit' value='Roll the dice'/> </form> </body> </html> If you need to choose between more than two conditions, you can emulate a switch statement simply by adding more <c:when> actions in the body of a <c:choose> action, as illustrated in the next section. Implementing Switch Statement ConstructsListing 3.14 lists a variation of the JSP page shown in Figure 3-9 on page 134 that illustrates how you can emulate a switch statement with the <c:choose>, <c:when>, and <c:otherwise> actions. Listing 3.14 Implementing Switch Statement Constructs<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Emulate a Switch Statement</title> </head> <body> <%@ taglib uri='http://java.sun.com/jstl/core' prefix='c' %> <%@ taglib uri='http://java.sun.com/jstl/core_rt' prefix='c_rt' %> <%-- Roll the dice --%> <c_rt:set var='roll'> <%= (int)(Math.random() * 7) %> </c_rt:set> <%-- Emulate a switch statement --%> <c:choose> <%-- If the roll was equal to 1 --%> <c:when test='${roll == 1}'> <img src='<c:out value="dice-${roll}.jpg"/>'> </c:when> <%-- If the roll was equal to 2 --%> <c:when test='${roll == 2}'> <img src='<c:out value="dice-${roll}.jpg"/>'> </c:when> <%-- If the roll was equal to 3 --%> <c:when test='${roll == 3}'> <img src='<c:out value="dice-${roll}.jpg"/>'> </c:when> <%-- If the roll was equal to 4 --%> <c:when test='${roll == 4}'> <img src='<c:out value="dice-${roll}.jpg"/>'> </c:when> <%-- If the roll was equal to 5 --%> <c:when test='${roll == 5}'> <img src='<c:out value="dice-${roll}.jpg"/>'> </c:when> <%-- If the roll was equal to 6 --%> <c:when test='${roll == 6}'> <img src='<c:out value="dice-${roll}.jpg"/>'> </c:when> <%-- Here, <c:otherwise> is the equivalent of a default in a switch statement --%> <c:otherwise> Oops, the dice rolled off the table! Try again. </c:otherwise> </c:choose> <%-- Because the following form has no action, this JSP page will be reloaded when the form is submitted --%> <form> <input type='submit' value='Roll the dice'/> </form> </body> </html> The preceding JSP page is functionally equivalent to the JSP page listed in Listing 3.13. The preceding JSP page tests each value that constitutes a valid dice role with individual <c:when> actions. In this case, we are testing for one condition out of seven, but you can easily generalize the JSP page to select one condition out of any number of conditions that you desire . |