B.4 Elements of JSP Pages
An earlier section of this appendix described some general
characteristics of JSP pages. This section discusses in more detail
the kinds of constructs you can use.
JSP pages are templates that contain static
parts and dynamic parts:
Literal text in a JSP page that is not enclosed within special
markers is static; it's sent to the client without
change. The JSP examples in this book produce HTML pages, so the
static parts of JSP scripts are written in HTML. But you can also
write pages that produce other forms of output, such as plain text,
XML, or WML.
The non-static (dynamic) parts of JSP pages consist of code to be
evaluated. The code is distinguished from static text by being
enclosed within special markers. Some markers indicate
page-processing directives or scriptlets. A directive gives the JSP
engine information about how to process the page, whereas a scriptlet
is a mini-program that is evaluated and replaced by whatever output
it produces. Other markers take the form of tags written as XML
elements; they are associated with classes that act as tag handlers
to perform the desired actions.
The following sections discuss the various types of dynamic elements
that JSP pages can contain.
B.4.1 Scripting Elements
Several sets of scripting markers
allow you to embed Java code or comments in a JSP page:
- <% ... %>
-
The <% and %> markers
indicate a scriptlet—that is, embedded Java code. The following
scriptlet invokes print( ) to write a value to the
output page:
<% out.print (1+2); %>
- <%= ... %>
-
These markers indicate an expression to be evaluated. The result is
added to the output page, which makes it easy to display values with
no explicit print statement. For example, these two constructs both
display the value 3, but the second is easier to write:
<% out.print (1+2); %>
<%= 1+2 %>
- <%! ... %>
-
The <%! and %> markers
allow class variables and methods to be declared.
- <%-- ... --%>
-
Text within these markers is treated as a comment and ignored. JSP
comments disappear entirely and do not appear in the output that is
returned to the client. If you're writing a JSP page
that produces HTML and you want the comment to appear in the final
output page, use an HTML comment instead:
<%-- this comment will not be part of the final output page --%>
<!-- this comment will be part of the final output page -->
When a JSP page is translated into a servlet, all scripting elements
effectively become part of the same servlet. This means that a
variable declared in one element can be used by other elements later
in the page. It also means that if you declare a given variable in
two elements, the resulting servlet is illegal and an error will
occur.
The <% ... %> and
<%! ... %> markers both
can be used to declare variables, but differ in their effect. A
variable declared within <% ...
%> is an object (or instance) variable; it is
initialized each time that the page is requested. A variable declared
within <%! ... %> is a
class variable, initialized only at the beginning the life of the
page. Consider the following JSP page,
counter.jsp, which declares
counter1 as an object variable and
counter2 as a class variable:
<%-- counter.jsp - demonstrate object and class variable counters --%>
<% int counter1 = 0; %> <%-- object variable --%>
<%! int counter2 = 0; %> <%-- class variable --%>
<% counter1 = counter1 + 1; %>
<% counter2 = counter2 + 1; %>
<p>Counter 1 is <%= counter1 %></p>
<p>Counter 2 is <%= counter2 %></p>
If you install the page and request it several times, the value of
counter1 will be 1 for every request. The value of
counter2 increments across successive requests
(even if different clients request the page), until Tomcat is
restarted.
In addition to variables that you declare yourself, JSP pages have
access to a number of objects that are declared for you implicitly.
These are discussed in "Implicit JSP
Objects."
B.4.2 JSP Directives
The
<%@ and %> markers
indicate a JSP directive that provides the JSP processor with
information about the kind of output the page produces, the classes
or tag libraries it requires, and so forth.
- <%@ page ... %>
-
page directives provide several kinds of
information, which are indicated by one or more
attribute="value"
pairs following the page keyword. The following
directive specifies that the page scripting language is Java and that
it produces an output page with a content type of
text/html:
<%@ page language="java" contentType="text/html" %>
This particular directive need not actually be specified at all,
because java and text/html are
the default values for their respective attributes.
If a JSP page produces non-HTML output, be sure to override the
default content type. For example, if a page produces plain text, use
this directive:
<%@ page contentType="text/plain" %>
An import attribute causes Java classes to be
imported. In a regular Java program, you would do this using an
import statement. In a JSP page, use a
page directive instead:
<%@ page import="java.util.Date" %>
<p>The date is <%= new Date ( ) %>.</p>
If you refer to a particular class only once, it may be more
convenient to omit the directive and just refer to the class by its
full name when you use it:
<p>The date is <%= new java.util.Date ( ) %>.</p>
- <%@ include ... %>
-
The include directive inserts the contents of a
file into the page translation process. That is, the directive is
replaced by the contents of the included file, which is then
translated itself. The following directive causes inclusion of a file
named my-setup-stuff.inc from the
application's WEB-INF
directory:
<%@ include file="/WEB-INF/my-setup-stuff.inc" %>
A leading / indicates a filename relative to the
application directory (a context-relative path). No leading
/ means the file is relative to the location of
the page containing the include directive.
Include files allow content (either static or dynamic) to be shared
easily among a set of JSP pages. For example, you can use them to
provide standard headers or footers for a set of JSP pages, or to
execute code for common operations such as setting up a connection to
a database server.
- <%@ taglib ... %>
-
A taglib directive indicates that the page uses
custom actions from a given tag library. The directive includes
attributes that tell the JSP engine how to locate the TLD file for
the library and also the name you'll use in the rest
of the page to signify tags from the library. For example, a page
that uses the core and database-access tags from JSTL might include
the following taglib directives:
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %>
The uri (Uniform Resource Identifier) attribute
uniquely identifies the tag library so that the JSP engine can find
its TLD file. The TLD defines the behavior (the interface) of the
actions so that the JSP processor can make sure the page uses the
library's tags correctly. A common convention for
constructing unique uri values is to use a string
that includes the host from which the tag library originates. That
makes the uri value look like a URL, but
it's just an identifier; it doesn't
mean that the JSP engine actually goes to that host to fetch the
descriptor file. The rules for interpreting the
uri value are described in Recipe B.4.4."
The prefix attribute indicates how tags from the
library will be invoked. The directives just shown indicate that core
and database tags will have the forms
<c:xxx>
and
<sql:xxx>.
For example, you can use the out tag from the core
library as follows to display a value:
<c:out value="Hello, world." />
Or you might issue a query with the database query
tag like this:
<sql:query var="result" dataSource="${conn}">
SHOW TABLES
</sql:query>
B.4.3 Action Elements
Action element tags can refer to
standard (predefined) JSP actions, or to custom actions in a tag
library. Tag names include a prefix and a specific action:
Tag names with a jsp prefix indicate predefined
action elements. For example, <jsp:forward>
forwards the current request to another page. This action is
available to any page run under a standard JSP processor.
Custom actions are implemented by tag libraries. The prefix of the
tag name must match the prefix attribute of a
taglib directive that appears earlier in the page,
so that the JSP processor can determine which library the tag is part
of. To use custom tags, the library must be installed first. See
"Using a Tag Library."
Actions are written as XML elements within a JSP page, and their
syntax follows normal XML rules. An element with a body is written
with separate opening and closing tags:
<c:if test="${x == 0}">
x is zero
</c:if>
If the tag has no body, the opening and closing tags can be combined:
<jsp:forward page="some_other_page.jsp" />
B.4.4 Using a Tag Library
Suppose that you have a tag library
consisting of a JAR file mytags.jar and a tag
library descriptor file mytags.tld. To make the
library available to the JSP pages in a given application, both files
must be installed. Typically, you'd put the JAR file
in the application's
WEB-INF/lib directory and the TLD file in the
WEB-INF directory.
A JSP page that uses the tag library must include an appropriate
taglib directive before using any of the actions
that the library provides:
<%@ taglib uri="tld-location" prefix="taglib-identifier" %>
The prefix attribute tells Tomcat how
you'll refer to tags from the library in the rest of
the JSP page. If you use a prefix value of
mytags, you can refer to tags later in the page
like this:
<mytags:sometag attr1="attribute value 1" attr2="attribute value 2">
tag body
</mytags:sometag>
The prefix value is a name of your own choosing,
but you must use it consistently throughout the page, and you cannot
use the same value for two different tag libraries.
The uri attribute tells the JSP processor how to
find the tag library's TLD file. The value can be
either direct or indirect:
You can specify the uri value directly as the
pathname to the TLD file, which typically will be installed in the
WEB-INF directory:
<%@ taglib uri="/WEB-INF/mytags.tld" prefix="mytags" %> A leading / indicates a filename relative to the
application directory (a context-relative path). No leading
/ means the file is relative to the location of
the page containing the taglib directive.
If an application uses lots of tag libraries, a common convention for
keeping TLD files from cluttering up the WEB-INF
directory is to put them in a tld subdirectory
of the WEB-INF directory. In that case, the
uri value would be written like this instead:
<%@ taglib uri="/WEB-INF/tld/mytags.tld" prefix="mytags" %> The disadvantage of specifying a TLD file pathname directly is that
if a new version of the tag library is released and the TLD file has
a different name, you'll need to modify the
taglib directive in every JSP page that refers to
the file.
Another way to specify the location of the TLD file is by using the
pathname to the tag library JAR file:
<%@ taglib uri="/WEB-INF/lib/mytags.jar" prefix="mytags" %> The JSP processor can find the TLD file this way, provided a copy of
it is included in the JAR file as
META-INF/taglib.tld. However, this method
suffers the same problem as specifying the TLD filename
directly—if a new version of the library comes out with a
different JAR file pathname, you must update
taglib directives in individual JSP pages. It also
doesn't work for containers that
can't find TLD files in JAR files. (Older versions
of Tomcat have this problem, for example.)
A third way to specify the location of the TLD file is to do so
indirectly. Assign a symbolic name to the library and add a
<taglib> entry to the
application's web.xml file that
maps the symbolic name to the pathname of the TLD file. Then refer to
the symbolic name in your JSP pages. Suppose you define the symbolic
name for the mytags tag library as:
http://terrific-tags.com/mytags The <taglib> entry in
web.xml should list the symbolic name and
provide the path to the corresponding TLD file. If the file is
installed in the WEB-INF directory, write the
entry like this:
<taglib>
<taglib-uri>http://terrific-tags.com/mytags</taglib-uri>
<taglib-location>/WEB-INF/mytags.tld</taglib-location>
</taglib>If the file is installed in WEB-INF/tld instead,
write the entry like this:
<taglib>
<taglib-uri>http://terrific-tags.com/mytags</taglib-uri>
<taglib-location>/WEB-INF/tld/mytags.tld</taglib-location>
</taglib>Either way, you refer to the tag library in JSP pages using the
symbolic name, like this:
<%@ taglib uri="http://terrific-tags.com/mytags" prefix="mytags" %> Using a symbolic TLD name involves a level of indirection, but has a
significant advantage in that it provides a more stable means by
which to refer to the tag library in JSP pages. You specify the
actual location of the TLD file only in web.xml,
rather than in individual JSP pages. If a new version of the tag
library comes out and the TLD file has a different name, just change
the <taglib-location> value in
web.xml and restart Tomcat to allow your JSP
pages to use the new library. There's no need to
change any of the JSP pages.
B.4.5 Implicit JSP Objects
When a servlet runs, the servlet
container passes it two arguments representing the request and the
response, but you must declare other objects yourself. For example,
you can use the response argument to obtain an
output-writing object like this:
PrintWriter out = response.getWriter ( );
A convenience that JSP provides in comparison to servlet writing is a
set of implicit objects—that is, standard objects that are
provided as part of the JSP execution environment. You can refer to
any of these objects without explicitly declaring them. Thus, in a
JSP page, the out object can be treated as having
already been set up and made available for use. Some of the more
useful implicit objects are:
- pageContext
-
An object that provides the environment for the page.
- request
-
An object that contains information about the request received from
the client, such as the parameters submitted in a form.
- response
-
The response being constructed for transmission to the client. You
can use it to specify response headers, for example.
- out
-
The output object. Writing to this object through methods such as
print( ) or println( ) adds
text to the response page.
- session
-
Tomcat provides access to a session that can be used to carry
information from request to request. This allows you to write
applications that interact with the user in what seems to the user as
a cohesive series of events. Sessions are described more fully in
Chapter 19.
- application
-
This object provides access to information that is shared on an
application-wide basis.
B.4.6 Levels of Scope in JSP Pages
JSP pages have access to several
scope levels, which can be used to store information that varies in
how widely available it is. The scope levels are:
- Page scope
-
Information that is available only to the current JSP page.
- Request scope
-
Information that is available to any of the JSP pages or servlets
that are servicing the current client request. It's
possible for one page to invoke another during request processing;
placing information in request scope allows such pages to communicate
with each other.
- Session scope
-
Information that is available to any page servicing a request that is
part of a given session. Session scope can span multiple requests
from a given client.
- Application scope
-
Information that is available to any page that is part of the
application context. Application scope can span multiple requests,
sessions, or clients.
One context knows nothing about other contexts, but pages served from
within the same context can share information with each other by
registering attributes (objects) in one of the scopes that are higher
than page scope.
To move information into or out of a given scope, use the
setAttribute( ) or getAttribute(
) methods of the implicit object corresponding to that
scope (pageContext, request,
session, or application). For
example, to place a string value tomcat.snake.net
into request scope as an attribute named myhost,
use the request object:
request.setAttribute ("myhost", "tomcat.snake.net");
setAttribute( ) stores the value as an
Object. To retrieve the value later, fetch it by
name using getAttribute( ) and then coerce it back
to string form:
Object obj;
String host;
obj = request.getAttribute ("myhost");
host = obj.toString ( );
When used with the pageContext object,
setAttribute( ) and getAttribute(
) default to page context. Alternatively, they can be
invoked with an additional parameter of
PAGE_SCOPE, REQUEST_SCOPE,
SESSION_SCOPE, or
APPLICATION_SCOPE to specify a scope level
explicitly. The following statements have the same effect as those
just shown:
pageContext.setAttribute ("myhost", "tomcat.snake.net",
pageContext.REQUEST_SCOPE);
obj = pageContext.getAttribute ("myhost", pageContext.REQUEST_SCOPE);
host = obj.toString ( );
|
Main Menu
|