Chapter 3
IN THIS CHAPTER
Seeing how servlets work
Dealing with page directives
Trying out expressions
Putting scriptlets to work
Devising declarations
Comprehending classes
In Book 7, Chapter 2, you discover how to create servlets that write HTML data directly to a page by using the PrintWriter
object accessed through response.out
. Although this technique works, it has one major drawback: You have to compose the HTML manually as a bunch of string literals. If the HTML has an error, you don’t know about it until you run the servlet to see how it looks. Also, handcrafting HTML in out.println
statements certainly isn’t the most efficient way to create attractive web pages.
That’s where JavaServer Pages (a technology usually called JSP for short) comes in. A JavaServer Page is an HTML file that has Java servlet code embedded in it in special tags. When you run a JSP, all the HTML is automatically sent as part of the response, along with any HTML that’s created by the Java code you embed in the JSP file. As a result, JSP spares you the chore of writing all those out.println
statements.
Note: To work with JavaServer Pages, you must first set up a working Tomcat environment. For information on how to do that, please refer to Book 7, Chapter 2.
A JSP is an HTML document that’s saved in a file with the extension .jsp
instead of .htm
or .html
. Unlike servlet-class files, a JSP file can be stored in any directory that’s available to the web server.
The first time a user requests a JSP file, the file is run through a translator program that converts the file to a Java servlet program and compiles it. All the HTML from the original JSP file is converted to out.print
statements that send the HTML to the response, and the Java statements from the JSP file are incorporated into the servlet program. Then the servlet program is executed and the results sent back to the browser.
Note that this translation occurs only once: the first time someone requests the JSP. After that, the servlet itself is run directly whenever a user requests the JSP.
Enough of the concept — now on to the code. When you create a JSP, you mix special JSP elements into your normal HTML. You can include four types of JSP elements:
import
statements the servlet requires, specify whether the servlet is thread-safe, and include other source files in the servlet. For example:
<%@ page import="java.util.*" %>
<%= expression %>
if
statements, looping, and calling other methods. You can even use out.println
to add output to the page; the output is inserted into the page at the location where the scriptlet appears. Scriptlets have the following form:
<% statements %>
<%! statements %>
The remaining sections of this chapter show you how to create JSP pages that incorporate these elements.
A page directive is a JSP element that sets options that determine how the JSP is converted to a servlet. The basic format of a page directive is this:
<%@ page attribute=value %>
The attribute can be any of the attributes listed in Table 3-1. (A few attributes besides these are available, but they’re rarely used.)
TABLE 3-1 Commonly Used Page Directive Attributes
Name |
Description |
|
Adds an |
|
Lets you specify the type of document created by the servlet. The default is |
|
If |
|
If |
|
Specifies the size of the buffer used by the |
|
Specifies the name of an error page that is displayed if this servlet throws an uncaught exception. |
|
If |
The page directive you use most is import
, as it lets you import the packages for API classes so that you can use them in expression, scriptlet, and declaration elements. Here’s a page directive that imports the java.util
package:
<%@ page import="java.util.*" %>
A JSP expression is any Java expression that evaluates to a string. Actually, the expression doesn’t have to evaluate directly. Here’s how you can use the java.util.Date
class to display the current date and time:
<%=new java.util.Date()%>
This expression creates a new instance of the java.util.Date()
class, which represents the current date and time. The toString()
method is implicitly called to convert this object to a string.
If you include a page import
directive, you can omit the qualification on this expression, as in this example:
<%@ page import="java.util" %>
<%=new Date()%>
To do more interesting things with expressions, you can use predefined variables, also known as implicit objects — Java variables that are available to expressions, scriptlets, or declarations throughout a JSP page. Table 3-2 lists the JSP implicit objects you use most often.
TABLE 3-2 Implicit Objects
Name |
Description |
|
Used to write data to the response; equivalent to |
|
Used as the request object; equivalent to the |
|
Used as the response object; equivalent to the |
|
Used to manage sessions; equivalent to |
The implicit objects work the same way that their corresponding objects do in servlets. The response
object, for example, is just the response
parameter that’s passed to the doGet
or doPost
method.
The implicit object you use most in expressions is request
. In particular, you use its getParameter
method to get values entered by the user in forms. Here’s an expression that displays the value entered in an input field titled Name
:
<%= request.getParameter("Name")%>
The value of the Name
field is inserted wherever this expression occurs in the JSP file. Here’s a simple JSP file named InputJSP.jsp
that displays an input text box and a button. When the user clicks the button, whatever text he or she entered in the input field is displayed below the button, as follows:
<html>
<head>
<title>Input JSP</title>
</head>
<body>
<form action="InputJSP.jsp" method="post">
Enter some text:
<input type="text" name="Text">
<br><br>
<input type="submit" value="Submit">
</form><br>
<h3>You entered:
<%= request.getParameter("Text")%></h3>
</body>
</html>
The HTML for this JSP defines a form that contains an input text field named Text
and a Submit button. When the user clicks the Submit button, an HTTP POST request is sent to the server to request InputJSP.jsp
. Any text entered by the user is sent along with the request. When the servlet is run, the text is retrieved by the expression request.getParameter("Text")
and displayed below the button. Figure 3-1 shows this servlet in action.
Note: Expressions can also call methods that you add to the JSP with declaration elements. You see examples of how to do that in the section “Using Declarations,” later in this chapter.
As mentioned earlier in the chapter, a scriptlet is a statement or group of statements that’s inserted directly into the servlet at the point where the out.print
statements that create the surrounding HTML are generated. In short, scriptlets let you add your own code to the code that renders the page.
Scriptlets follow this basic form:
<% statements… %>
Here’s a JSP named DateJSP.jsp
that uses the DateFormat
class to format the date and display it on the page:
<html>
<%@ page import="java.text.*" %>
<%@ page import="java.util.*" %>
<head>
<title>Date JSP</title>
</head>
<body>
<h1>
Today is
<%
DateFormat df = DateFormat.getDateInstance(
DateFormat.FULL);
Date today = new Date();
String msg = df.format(today);
out.println(msg);
%>
</h1>
<h1>Have a nice day!</h1>
</body>
</html>
This JSP begins with a pair of page import
directives to import the java.text
and java.util
packages. Then the following Java statements are inserted right between the lines that generate the text Today is
and Have a nice day!
, like so:
DateFormat df
= DateFormat.getDateInstance(DateFormat.FULL);
Date today = new Date();
String msg = df.format(today);
out.println(msg);
These lines create a string variable named msg
and then use out.println
to write the string to the response output. As a result, the formatted date is inserted between <h1>Today is </h1>
and <h1>Have a nice day!</h1>
. Figure 3-2 shows a page generated by this JSP.
If you want, you can get pretty tricky with scriptlets. No rule says that you have to complete block statements such as if
or while
statements within a single scriptlet. If you leave a block open at the end of a scriptlet, any HTML that follows is generated by out.print
statements that are included in the block. The only restriction is that you must eventually end the block with another scriptlet.
Here’s a scriptlet named LoopyJSP.jsp
that repeats a line 12 times on the page by including the line in the block of a for
loop:
<html>
<head>
<title>Can't you see I'm trying to work here?</title>
</head>
<body>
<% for (int i = 0; i < 12; i++)
{
%>
All work and no play makes Jack a dull boy.<br>
<%
}
%>
</body>
</html>
If you run this scriptlet, the page appears as shown in Figure 3-3.
A declaration is code that is included in the servlet but outside any method. Declarations are used to create class variables or methods that can be used in expressions, scriptlets, or other declarations. Declarations follow this format:
<%! Statements… %>
You can place declarations anywhere you want in a JSP.
Here’s a servlet that declares a static class field named count
that’s incremented each time the page is displayed:
<html>
<%@ page import="java.text.*" %>
<%@ page import="java.util.*" %>
<head>
<title>Counter JSP</title>
</head>
<body>
<h1>
This JSP has been displayed <%= count++ %>
time.</h1>
</body>
</html>
<%!
private static int count = 1;
%>
In this servlet, the count
variable is declared by the declaration element at the end of the JSP document, as follows:
<%!
private static int count = 1;
%>
Then the expression in the body of the document displays and increments the count
variable, like this:
<%= count++ %>
When run, the JSP displays the number of times the page has been displayed since the server started.
Here’s another example, this time declaring a method that’s called in an expression:
<html>
<%@ page import="java.text.*" %>
<%@ page import="java.util.*" %>
<head>
<title>Date JSP</title>
</head>
<body>
<h1>
Today is <%= getDate() %></h1>
<h1>Have a nice day!</h1>
</body>
</html>
<%!
private String getDate()
{
DateFormat df =
DateFormat.getDateInstance(DateFormat.FULL);
Date today = new Date();
return df.format(today);
}
%>
The declaration at the end of this document declares a method that returns the current date as a string. Then the expression <%= getDate() %>
is used to insert the date into the document.
Most JSP applications are complicated enough that they need additional classes to keep their code manageable. Maybe you want to create classes that handle the application’s file or database I/O, and you want to create classes to represent business objects such as Products
and Customers
.
Setting up Tomcat to work with classes can be a little tricky, but it’s easy if you follow these simple guidelines:
package
statement to the beginning of each class file.WEB-INFclassespackage
directory below the directory in which the JSP pages are stored. If the package name is com.lowewriter.movie
, and you’re storing your JSP pages in c: omcatwebappsROOT
, save the class files in the following directory:
C: omcatwebappsROOTWEB-INFclassescomlowewritermovie
<%@ page import="com.lowewriter.movie.*" %>
ClassPath
environment variable. You want to add the directory that contains the packages, not the directory that contains the classes themselves, because the Java compiler uses the package name to find the package directory. So if you put your classes in the webappsROOTWIB-INFclasses
directory, you need to add c: omcatwebappsROOTWEB-INFclasses
to your ClassPath
.To illustrate how a JSP can use classes, Figure 3-4 shows a JSP that lists the movies in the movies.txt
file. The JSP file that displays this page is shown in Listing 3-1. The JSP file itself is stored in c: omcatwebappsROOT
.
LISTING 3-1 ListMovies.jsp
<!doctype html public "-//W3C//DTD HTML 4.0
Transitional//EN">
<%@ page import="com.lowewriter.movie.*" %> →3
<%@ page import="java.util.*" %>
<html>
<head>
<title>List Movies: The Servlet</title>
</head>
<body>
<h1>Some of My Favorites</h1>
<h3>
<%= getMovieList() %> →12
</h3>
</body>
</html>
<%!
private String getMovieList() →18
{
String msg = "";
ArrayList<Movie> movies = MovieIO.getMovies(); →21
for (Movie m : movies) →22
{
msg += m.year + ": ";
msg += m.title + "<br>";
}
return msg; →28
}
%>
Following is an explanation of the key lines in this JSP:
com.lowewriter.movie
and java.util
packages.getMovieList
method, which returns the list of movies to be displayed as a string.getMovieList
method is defined in a declaration.getMovies
method of the MovieIO
class is called to retrieve an ArrayList
that contains all the movies from the movies.txt
file.Movie
objects are retrieved from the ArrayList
, and the year and title are added to the msg
string.msg
string is returned.Listing 3-2 shows the Movie
class. There’s nothing special to note here other than the package
statement that places the Movie
class in the com.lowewriter.movie
package. The class file that’s compiled from this .java
file is saved in c: omcatwebapsROOTWEB-INFclassescomlowewritermovie
.
LISTING 3-2 Movie.java
package com.lowewriter.movie;
public class Movie
{
public String title;
public int year;
public double price;
public Movie(String title, int year,
double price)
{
this.title = title;
this.year = year;
this.price = price;
}
}
Finally, the MovieIO
class is shown in Listing 3-3. This class reads the movies from a text file. (For a detailed explanation of how this class works, jump forward to Book 8, Chapter 2.) Notice that this class, like the Movie
class, includes a package
statement that dumps the MovieIO
class into the movie package. The class file compiled from this .java
file is saved in c: omcatwebapsROOTWEB-INFclassescomlowewritermovie
.
LISTING 3-3 MovieIO.java
package com.lowewriter.movie;
import java.io.*;
import java.util.*;
public class MovieIO
{
public static ArrayList<Movie> getMovies()
{
ArrayList<Movie> movies =
new ArrayList<Movie>();
BufferedReader in =
getReader("c:\data\movies.txt");
Movie movie = readMovie(in);
while (movie != null)
{
movies.add(movie);
movie = readMovie(in);
}
return movies;
}
private static BufferedReader getReader(
String name)
{
BufferedReader in = null;
try
{
File file = new File(name);
in = new BufferedReader(
new FileReader(file) );
}
catch (FileNotFoundException e)
{
System.out.println(
"The file doesn't exist.");
System.exit(0);
}
return in;
}
private static Movie readMovie(BufferedReader in)
{
String title;
int year;
double price;
String line = "";
String[] data;
try
{
line = in.readLine();
}
catch (IOException e)
{
System.out.println("I/O Error");
System.exit(0);
}
if (line == null)
return null;
else
{
data = line.split(" ");
title = data[0];
year = Integer.parseInt(data[1]);
price = Double.parseDouble(data[2]);
return new Movie(title, year, price);
}
}
}