In the previous chapter, 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. And hand-crafting HTML in out.println statements certainly isn't the most efficient way to create attractive Web pages.
That's where Java Server Pages (usually called JSP for short) come in. A JSP 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.
In this chapter, you find out how to create basic Java Server Pages. Then, in the next chapter, I show you how to incorporate special Java classes called JavaBeans into your JSP pages.
A Java Server Page is an HTML document that's saved in a file with the extension .jsp instead of .htm or .html. Unlike servlet class files, you can store a JSP file in any directory that's available to the Web server.
The first time a user requests a JSP file, the JSP file is run through a translator program that converts the file into 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:
<%= expression %>
<% statements %>
<%! statements %>
The remaining sections of this chapter show you how to create JSP pages that incorporate each of 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. (There are a few other attributes besides these, but they're rarely used.)
Name |
Description |
---|---|
import=“package.class” |
Adds an import statement to the servlet so you can use classes in other JSP elements without having to fully qualify them. |
content-Type=“MIME-type” |
Lets you specify the type of document created by the servlet. The default is text/html. You rarely need to change this. |
isThreadSafe=“boolean” |
If true, the servlet is assumed to be thread-safe. If false, implements SingleThreadModel is added to the servlet class declaration so that the thread runs in the single thread model. The default is true. |
session=“boolean” |
If true, the servlet uses session management. The default is true. |
buffer=“size” |
Specifies the size of the buffer used by the out variable. The default depends on the server, but is never smaller than 8K. |
errorPage=“URL” |
Specifies the name of an error page that is displayed if this servlet throws an uncaught exception. |
isErrorPage=“boolean” |
If true, this page is an error page for some other JSP page. The default is false. |
The page directive you use most is import, as it lets you import the packages for API classes so you can use them in expression, scriptlet, and declaration elements. For example, here's a page directive that imports the java.util package:
<%@ page import="java.util.*" %>
You can place page directives anywhere you want in a JSP document, but I suggest you place them at or near the top.
A JSP expression is any Java expression that evaluates to a string. Actually, the expression doesn't have to evaluate directly. For example, 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. For example:
<%@ page import="java.util" %> <%=new Date()%>
To do more interesting things with expressions, you can use predefined variables, which are also known as implicit objects. These are 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.
Name |
Description |
---|---|
out |
Used to write data to the response, equivalent to response. getWriter() in a servlet. |
request |
The request object, equivalent to the request parameter in the doGet or doPost method of a servlet. |
response |
The response object, equivalent to the response parameter in the doGet or doPost method of a servlet. |
session |
Used to manage sessions. Equivalent to request.getSession() in a servlet. |
The implicit objects work the same as their corresponding objects do in servlets. For example, the response object is actually just the response parameter that's passed to the doGet or doPost method.
The implicit object you use most in expressions is the request object. In particular, you use its getParameter method to get values entered by the user in forms. For example, here's an expression that displays the value entered in an input field named Name:
<%= request.getParameter("Name")%>
The value of the Name field is inserted wherever this expression occurs in the JSP file. For example, here's a simple JSP 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 beneath the button:
Input JSP
Enter some text:
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 beneath the button. Figure 3-1 shows this servlet in action.
Figure 3-1: InputJSP 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 later in this chapter, in the section "Using Declarations." |
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... %>
For example, here's a JSP named DateJSP.jsp that uses the DateFormat class to format the date and display it on the page:
<%@ page import="java.text.*" %> <%@ page import="java.util.*" %>Date JSP
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!:
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
and
. Figure 3-2 shows a page generated by this JSP.
Figure 3-2: DateJSP in action.
Note |
Scriptlets don't have to add anything to the HTML output. In many cases, they perform functions such as writing information to a file. For example, suppose you have a JSP that gets data from a form that includes input text fields named FirstName and LastName. Suppose also that you have a class named CustFile with a static method named writeCustomer that accepts a first and last name as parameters and writes them to a file. Here's a scriptlet that gets the first and last names and calls the writeCustomer method to write the name to the customer file: <% String firstName = request.getParameter("FirstName"); String lastName = request.getParameter("LastName"); CustFile.writeCustomer(firstName, lastName); %> |
If you want, you can get pretty tricky with scriptlets. No rule says 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.
For example, 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:
Can't<% for (int i = 0; i < 12; i++) { %> All work and no play makes Jack a dull boy.
<% } %>
If you run this scriptlet, the page appears as shown in Figure 3-3.
Figure 3-3: LoopyJSP. jsp doing its thing.
Warning |
Obviously, this sort of programming structure is prone to error. I suggest you avoid it whenever you can. |
A declaration is code that is included in the servlet but outside of 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:
<%@ page import="java.text.*" %> <%@ page import="java.util.*" %>Counter JSP
<%! private static int count = 1; %>
In this servlet, the count variable is declared by the declaration element at the end of the JSP document:
<%! private static int count = 1; %>
Then the expression in the body of the document displays and increments the count variable:
<%= 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:
<%@ page import="java.text.*" %> <%@ page import="java.util.*" %>Date JSP
<%! 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. For example, you want to create classes that handle the application's file or database I/O, and you may want to create classes to represent business objects such as Products or Customers.
Setting up Tomcat to work with classes can be a little tricky, but it's easy if you follow these simple guidelines:
C: omcatwebappsROOTMoviesWEB-INFclassesmovie
<%@ page import="movie.*" %>
To illustrate how a JSP can use classes, Figure 3-4 shows a JSP that lists the movies in the movies.txt file.
Figure 3-4: The ListMovies JSP in action.
The JSP file that displayed this page is shown in Listing 3-1. The JSP file itself is stored in c: omcatwebappsROOT.
Listing 3-1: ListMovies.jsp
<%@ page import="movie.*" %> → 3 <%@ page import="java.util.*" %>
List Movies: The Servlet
<%! private String getMovieList() → 18 { String msg = ""; ArrayList movies = MovieIO.getMovies(); → 21 for (Movie m : movies) → 22 { msg += m.year + ": "; msg += m.title + "
"; } return msg; → 28 } %>
Following is an explanation of the key lines in this JSP:
→ 3 |
The JSP includes two page directives that import the movie and java.util packages. |
→ 12 |
An expression is used to call the getMovieList method, which returns the list of movies to be displayed as a string. |
→ 18 |
The getMovieList method is defined in a declaration. |
→ 21 |
The getMovies method of the MovieIO class is called to retrieve an ArrayList that contains all the movies from the movies.txt file. |
→ 22 |
The Movie objects are retrieved from the ArrayList and the year and title are added to the msg string. |
→ 28 |
The finished msg string is returned. |
Open table as spreadsheet
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 movie package. The class file that's compiled from this .java file is saved in c: omcatsharedclassesmovie.
Listing 3-2: Movie.java
package 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 VIII, 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: omcatsharedclassesmovie.
Listing 3-3: MovieIO.java
package movie; import java.io.*; import java.util.*; public class MovieIO { public static ArrayList getMovies() { ArrayList movies = new ArrayList(); 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); } catch (IOException e) { System.out.println("I/O Error"); 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); } } }
Book I - Java Basics
Book II - Programming Basics
Book III - Object-Oriented Programming
Book IV - Strings, Arrays, and Collections
Book V - Programming Techniques
Book VI - Swing
Book VII - Web Programming
Book VIII - Files and Databases
Book IX - Fun and Games