5.3 JSTL
EL saves the day by beautifully simplifying the JSP, but sometimes we need more than it. For example, can you express if
or for
in EL? The answer is no. To this end, custom tags are designed. They look like HTML tags, but they can help you express logics (e.g., if
and for
) while getting away from scripting. Even better, the community has already written a pile of tags you're most likely to need, and bundled then into the JSP Standard Tag Library (JSTL).
How to install JSTL
JSTL is not part of the JSP specification[1], so we have to download both its API and implementation in our project. However, the latest version of JSTL in javax
namespace is 1.2.2, and it depends on servlet-api:2.5
, el-api:2.2
and jsp-api:2.2
. So there may be packages version conflicts problems. To solve those conflicts, we shall exclude them in the dependency:
implementation('org.glassfish.web:javax.servlet.jsp.jstl:1.2.5') {
exclude group: 'javax.el', module: 'el-api'
exclude group: 'javax.servlet', module: 'servlet-api'
exclude group: 'javax.servlet.jsp', module: 'jsp-api'
}
Then in the JSP file, we add the taglib directive:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Where prefix
is a customized prefix name, and you can use other names if you like; you can think of uri
as an address or a namespace, which looks like a URL. It must start with http://java.sun.com/jsp/jstl in JSTL 1.2, and core
is one of tag libraries[2].
JSTL examples
In this subsection, we will learn how to use JSTL through examples, and the code can be found at ch5/jstl
.
[!NOTE] Similar to HTML tags, different tags in JSTL have different attributes, and some are optional while some are required.
Suppose foo
is not the attribute's name, then ${foo}
won't output anything. But if we would like to output a default value when it is empty:
<c:out value="${user}" default="Guest"/>
Where <c:out>
is a tag defined in JSTL, and c
is the prefix we defined in the taglib directive.
Suppose an array is put into the attribute,
String[] books = {"Gone with the Wind", "The Great Gatsby",
"1587, a Year of No Significance"};
request.setAttribute("bookArray", books);
Let's iterate an array in the attribute.
<c:forEach var="book" items="${bookArray}">
${book}
</c:forEach>
As we see, <c:forEach>
can replace for
in the scriptlet.
<c:if>
is able to replace if
:
<c:if test="${balance > 88}">
You are rich.
</c:if>
Where test
attribute accepts a boolean value. Note that if we use a String literal, it should be enclosed with the single quote.
<c:if test="${name == 'Mary'}">
You are Mary.
</c:if>
However, <c:if>
tag cannot express else
. If you would like to express if...else
, you can use <c:choose>
tag:
<c:choose>
<c:when test="${balance > 88}">
You are rich.
</c:when>
<c:otherwise>
You are poor.
</c:otherwise>
</c:choose>
There are a plenty of tags defined in JSTL, but basically, <c:forEach>
, c:if>
and <c:choose>
can cover most of your daily programming tasks.
As a final example, let's try to iterate a Map.
Map<String, Integer> bookCount = new HashMap<>();
bookCount.put("Gone with the Wind", 42);
bookCount.put("The Great Gatsby", 100);
bookCount.put("1587, a Year of No Significance", 130);
request.setAttribute("bookCount", bookCount);
<c:forEach var="book" items="${bookCount}">
${book.key}
${book.value}
</c:forEach>
[1] In the book, we use Java EE 8 with servlet-api:4.0.1
, el-api:3.0.0
and jsp-api:2.3.3
, and both APIs and implementations are provided by the container. See more at Apache Tomcat Versions.
[2] There are other tag libraries, such as fmt
and sql
. It is a convention to use c
as the prefix for core
tag library. You can even write you own tags, but this is also considered bad.