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 scriptletthat 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 --%>
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; %>
Counter 1 is <%= counter1 %>
Counter 2 is <%= counter2 %>
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" %>
The date is <%= new Date ( ) %>.
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:
The date is <%= new java.util.Date ( ) %>.
<%@ 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 xxx> and xxx>. For example, you can use the out tag from the core library as follows to display a value:
Or you might issue a query with the database query tag like this:
SHOW TABLES
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, 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:
x is zero
If the tag has no body, the opening and closing tags can be combined:
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:
tag body
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 directlyif 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 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 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:
http://terrific-tags.com/mytags /WEB-INF/mytags.tld
If the file is installed in WEB-INF/tld instead, write the entry like this:
http://terrific-tags.com/mytags /WEB-INF/tld/mytags.tld
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 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 objectsthat 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 ( );
Appendix C References
|