I think it helps more if you see with your own eyes that it can actually be done entirely without scriptlets.
Here's a 1 on 1 rewrite with help of under each JSTL (just drop jstl-1.2.jar
in /WEB-INF/lib
) core and functions taglib:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<html>
<head>
<title>My Events - <decorator:title /></title>
<link href="${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="tabs">
<a
${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''}
href="${pageContext.request.contextPath}/events/Listing.action">Events</a>
<a
${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''}
href="${pageContext.request.contextPath}/people/Listing.action">People</a>
</div>
<div class="submenu">
<c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}">
<a href="Listing.action">List of Events</a>
|<a href="New.action">New Event</a>
</c:if>
<c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}">
<a href="Listing.action">List of People</a>
|<a href="New.action">New Person</a>
</c:if>
</div>
Here's a more optimized rewrite, note that I used c:set
to "cache" expression results for reuse and that I use HTML <base>
tag to avoid putting the context path in every link (just make all relative URL's in your webpage relative to it --without the leading slash!):
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" />
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" />
<html>
<head>
<title>My Events - <decorator:title /></title>
<base href="${pageContext.request.contextPath}">
<link href="assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="tabs">
<a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a>
<a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a>
</div>
<div class="submenu">
<c:if test="${isEvents}">
<a href="Listing.action">List of Events</a>|<a href="New.action">New Event</a>
</c:if>
<c:if test="${isPeople}">
<a href="Listing.action">List of People</a>|<a href="New.action">New Person</a>
</c:if>
</div>
It can actually be optimized more if you collect all those "hardcoded" values like events
and people
and link texts in a Map
in the application scope and use under each the JSTL <c:forEach>
to display the tabs.
As to your actual question, you can disable scriptlets (and get runtime errors about using it) by adding the following entry in webapp's web.xml
. It may help to spot overseen scriptlets.
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
To learn more about EL, check the Java EE tutorial part II chapter 5. Implicit EL objects, such as ${pageContext}
are described here. To learn more about JSTL, check the Java EE tutorial part II chapter 7. Note that JSTL and EL are two separate things. JSTL is a standard taglib and EL just enables to access backend data programmatically. Although it is normally used in taglibs like JSTL, it can also be used standalone in template text.