Many developers criticized the original JSP specification because it lacked some important basic capabilities. As we saw earlier in the chapter, you can implement complex logic within JSPs by embedding scriptlets. This approach works (at least, it’s functional and produces web pages that look about right), but it makes JSPs look a lot less like HTML and a lot more like Java code. As a result, the range of people who can work on them is sharply limited. To make things even worse, because developers were virtually forced into embedding large amounts of Java code into each page (at least if the page were in any way complex), business logic had a tendency to creep down into the presentation layer.
The JSP EL removes some of the need for scriptlets (you can now display a variable without embedding Java code directly) but doesn’t help implement page logic. That’s where the JSP Standard Tag Library (JSTL ) comes in. JSTL is not directly part of the JSP standard, but it’s an associated standard, and JSTL Version 1.1 (which is compatible with JSP 2.0) is also included in J2EE 1.4. In this section, we’ll discuss the most commonly used JSTL tags for variable handling, flow control, and internationalization.
The JSTL tags are easy to incorporate into your web applications. J2EE 1.4- compatible containers include all the necessary jar files. Standalone servlet/JSP containers, such as Tomcat, don’t, so you’ll need to obtain both the jstl.jar file and an implementation of the tags themselves separately. The reference implementation for JSTL grew out of the Jakarta taglibs project, and can be downloaded from http://jakarta.apache.org/taglibs/index.html. Put both jar files (the implementation from Jakarta is in standard.jar) into your WEB-INF/lib directory.
Once the JSTL tags are available to the web application, you need to map them to a namespace for each JSP. This is easy enough; just add the following line to the top of each page:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
By convention, the JSTL tags are given the prefix c
.
The <c:set>
and <c:remove>
tags provide basic variable handling for JSPs. In
general, these tags should be used carefully: you very rarely need
to manipulate variables within the JSP itself, other than possibly
for page layout purposes, and in most cases the EL will suffice. But
if you must, the following JSP file retrieves a variable from the
request parameter (using the built-in param object and an EL
expression), sets it to a session variable, displays the variable,
and then removes the variable from the session:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <c:set var="username" scope="session" value="${param.username}"/> <c:out value="${username}" escapeXML="false"/> <c:remove var="username"/> </html>
This JSP also uses the <c:out>
tag to display the variable. This tag was, before JSP
2.0, the only nonscriptlet method to display a variable in a JSP.
Now that we have the EL, the use of <c:out>
, which is much clunkier, can
be reduced but not quite eliminated. Unlike a regular EL expression,
the <c:out>
tag escapes all
XML characters into XML/HTML-safe entities. The >
character becomes <
and so on. If you expect to
display variables that might include HTML or XML reserved
characters, you should use <c:out>
rather than embedding the
bare expression into the page.
JSTL includes tags for loops and conditional logic, freeing
the page author from the tyranny of scriptlets. We saw one of
these tags, <c:if>
, in the previous section. The <c:if>
tag evaluates an EL
expression to true or false and, if true, processes the JSP code
contained within the tag.
There is no corresponding else
tag—you need to use another
<c:if>
with an inverse
condition or, if there are multiple conditions, the <c:choose>
tag. In the following extremely contrived example,
we display one message if a variable is 1 or below, another if it
is 2 or 3, and a final message if it’s greater than 3. The first
two determinations are made using the <c:when>
tag, which evaluates a conditional within a
choose
block, and the final
message is displayed using a <c:otherwise>
tag, which provides an optional fall-through
action:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <c:set var="niftylevel" value="5"/> <c:choose> <c:when test="${niftylevell < 2}"> Not terribly nifty. </c:when> <c:when test="${niftylevel > 1 and niftylevel < 4}"> Nifty, but could be niftier. </c:when> <c:otherwise> Remarkably nifty. </c:otherwise> </c:choose>
Processing stops when a condition is met—so setting the
niftylevel
variable to 3 after
printing out the first message does not cause the second message
to print.
Finally, JSTL includes a very robust loop tag, <c:forEach>
. This tag accepts any standard Collection
implementation, any standard
Map
implementation, arrays of
primitive types, and even strings containing comma-separated
values.[22]
In this example, the request attribute catalog
contains an ArrayList
holding a set of Product
objects. The JSP works through
the list, creating a temporary page variable named product
and printing out each list
entry.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Widget Catalog</title></head> <body> <ul> <c:forEach var="product" items="${catalog}"> <li>${product.name}: $${product.price}</li> </c:forEach> </ul> </body> </html>
JSTL provides basic support for URL management. This
functionality is important if you are using URL rewriting to track
sessions and can also simplify page design if you’re assembling
complex URLs. The <c:url>
tag simply accepts a (content-relative) URL and an
optional set of request parameters and displays a properly
formatted URL.
For example, in our catalog example, we could replace the
contents of the <c:forEach>
tag with the following
code to produce a URL that would link to a product detail page,
passing in the product’s Stock Keeping Unit (SKU) code as a URL
parameter named productID
:
<c:url var="producturl" value="/product" > <c:param name="productID" value="${product.SKU}" /> </c:url> <li><a href="${producturl}">${product.name}</a> - $${product.price}</li>
JSTL includes tags that support the Java
internationalization standards. Unlike the tags we’ve looked at so
far, the internationalization formatting tags reside in the fmt
package rather than the core
package.
Java’s internationalization functions, in a proverbial nutshell, let developers move the display constants from an application to an external properties file, also known as a resource bundle. The properties file can then be translated into other languages, making it easy to write multilingual applications. The strings are kept in the standard properties file format:
first.name=First Name last.name=Last Name
To use these two properties in a JSP file, we first make the
properties file accessible to the web application by placing it in
the classpath. If we name the file
messages.properties and place it in
WEB-INF/classes, we have created a resource
bundle named messages
. To provide
other languages, we provide other files with the same base name
followed by the two-character language code for the language in
question. A German language resource bundle would be named
messages_dk.properties and an explicitly
English language bundle would be called
messages_en.properties.
The <fmt:message>
and <fmt:bundle>
tags handle message display. Consider the JSP in
Example 4-1.
Example 4-1. message.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Message Bundle Example</title></head> <body> <form> <fmt:bundle basename="messages"> <table> <tr><td> <fmt:message key="first.name"/> </td><td><input type="text" name="firstname"></td></tr> <tr><td> <fmt:message key="last.name"/> </td><td><input type="text" name="lastname"></td></tr> </table> </fmt:bundle> <input type="submit" value="Submit"> </form> </body> </html>
The <fmt:bundle>
tag
sets the message bundle using the basename
attribute. The two <fmt:message>
tags retrieve the
messages from the resource bundle by name. The resulting page looks
like Figure
4-4.
It’s possible to skip the <fmt:bundle>
tag, either by using
the <fmt:setBundle>
tag (which sets the bundle for the entire page) or by
including a bundle
attribute on
the <fmt:message>
tag
itself.
[22] Iterator
and Enumeration
objects are also
supported, but with limits, since both types of objects can be
processed only once.
Get Java Enterprise in a Nutshell, Third Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.