A JSP is an HTML page with special tags embedded in it to allow the page to access the Web stream or enable it to access other Java objects. There are different types of JSP tags depending on their use:
Predefined VariablesThe JSP specification defines a set of predefined variables that can be used in a JSP. These variables help you access the request, the session, and other variables in the JSP runtime. The variables are part of the servlet that is created from the JSP:
This statement writes the specified message to the servlet log file.
ExpressionsExpressions are used to insert strings and other variables into the output of the JSP stream. A variable is converted to a string by the JSP engine if needed. Expressions allow dynamic information to be embedded into an HTML page by being interpreted with the HTML stream. For example, you can modify the Chapter 17 example so that it's a JSP. To do so, you write HTML code with embedded expressions that generate the same output as the servlet did, as shown in Listing 18.1. Listing 18.1 HTML Code with Embedded Expressions<html> <head> <title>Hello!</title> </head> <body> <!--- get the remote host, very similar to the servlet example --> Welcome <%= request.getRemoteHost() %> <br> <!--- get the User-Agent - also similar to the servlet example --> Your browser id string is <%= request.getHeader( "User-Agent" ) %> </body> </html> In this case, the JSP engine does not need to coerce the result of the call to getRemoteHost() because it already is a string. However, you can now add code to display the content length by calling getContentLength() on the request. This code returns an integer that is simply the length in bytes of the content after the HTTP header (see Listing 18.2). Listing 18.2 Displaying Information from the HttpServletRequest<html> <head> <title>Hello!</title> </head> <body> <!--- get the remote host, very similar to the servlet example --> Welcome <%= request.getRemoteHost() %> <br> <!--- display the Content-Length HTTP header element --> The Content-Length field is <%= request.getContentLength() %><br> <!--- get the User-Agent - also similar to the servlet example --> Your user agent string is <%= request.getHeader( "User-Agent" ) %> </body> </html> By automatically converting the result of getContentLength() to a string from an integer, the JSP engine further simplifies the task of writing a JSP page. The code does not require you to write something like this: The Content-Length field is <%= Integer.toString( request.getContentLength() ) %><br> Again, the goal is to minimize the amount of Java code that a JSP developer needs to write. Ultimately, all the output from the JSP page is a string that will be rendered by the browser like in Figure 18.1. Figure 18.1. Output from the sample JSP.
Expressions can also be included in a JSP with XML syntax. The syntax in Listing 18.1 would then be changed to that shown in Listing 18.3. Listing 18.3 Using JSP XML Expressions<html> <head> <title>Hello!</title> </head> <body> <!--- get the remote host, very similar to the servlet example --> Welcome <jsp:expression> request.getRemoteHost() </jsp:expression> <br> <!--- get the User-Agent - also similar to the servlet example --> Your user agent string is <jsp:expression> request.getHeader( "User-Agent" ) </jsp:expression> </body> </html> XML syntax improves the machine readability of the document and provides the flexibility of performing an XML transformation to programmatically change the page from one style to another, but can make it more difficult for human readability. However, the JSP engine treats both forms exactly the same, so it is up to you to determine the best form. DeclarationsA JSP declaration defines a variable to be used in a later scriptlet or expression. It has the form <%! declaration %> (see Listing 18.4). Listing 18.4 Using JSP Declarations<html> <head> <title>Hello!</title> <body> <%! private String lastVisitor = null; %> <b>Hello <%= request.getRemoteHost() %></b><br> The last visitor to our site came from <%= lastVisitor %> <% lastVisitor = request.getRemoteHost(); %> </body> </html> In Listing 18.4, the string, lastVisitor , is defined by the declaration and then used later in the expression. The last line sets the lastVisitor variable to the current visitor's remote host. It is important to understand that the JSP compiler translates declarations into member variables in the servlet. This means that multiple invocations of the same JSP use the same variable. Recall from Chapter 17 that the default behavior for servlets is for all requests to be serviced by the same servlet but through multiple threads. The same is true of JSP pages because they are servlets. However, this means that the same caveats that apply to servlets and threads also apply to JavaServer Pages. Listing 18.4 does not use synchronization techniques to serialize access to the variable lastVisitor . If multiple simultaneous requests come in to this JSP from different remote machines, the variable could be overwritten with incorrect information. One way to add thread safety to Listing 18.4 is to use standard Java synchronization techniques. Listing 18.5 shows using these techniques. Listing 18.5 JSP Declaration Example Using Synchronization<html> <head> <title>Hello!</title> <body> <%! private String lastVisitor = null; %> <b>Hello <%= request.getRemoteHost() %></b><br> The last visitor to our site came from <% synchronized( this ) { %> <%= lastVisitor %> <% lastVisitor = request.getRemoteHost(); } %> </body> </html> As with JSP expressions, there is an XML syntax for declarations too: <jsp:declaration> // // an alternate way to declare the same variable as in // Listing 18.4 // private String lastVisitor; </jsp:declaration> After you restart the server and run the JSP, the lastVisitor variable is null; hence, you will see the output shown in Figure 18.2. Figure 18.2. Output from the first run after a server restart.
After the JSP has been run once, the lastVisitor variable is set correctly, as shown in Figure 18.3. Figure 18.3. Output from the second run after a server restart.
ScriptletsThe last line of the syntax shown in Listing 18.4 <% lastVisitor = request.getRemoteHost() %> is slightly different because it represents a JSP scriptlet . A scriptlet allows the developer to embed any Java code within the JSP page. In this example, you reset the contents of the lastVisitor variable to be the current visitor so that on the next visit to the page the variable will display the correct output. Scriptlets can be used anywhere within the JSP. They must be used for code that is not meant to be converted into a string and inserted into the output HTML stream. In Listing 18.4, when you reassigned the lastVisitor variable, no output needed to be generated; only code needed to be executed in this case. Other Scripting ElementsWhen creating a JSP with scriptlets, you may need to import classes to use within the JSP. You do so with the page directive: <%@ page import="java.util.*, java.math.*" %> This directive generates an import statement in the resulting servlet. Page directives traditionally live at the top of the JSP. Several other page attributes are commonly used:
Another directive is include , which allows you to include another file within your JSP. There are two types of include directives. The first uses syntax similar to the page directive. It looks like this: <%@ include file="header.html" %> This directive tells the JSP compiler to include the entire contents of the header.html line in the JSP. The JSP compiler does not compile the JSP until it has included all files specified with the include directives. After the compiler includes all the files, it translates the JSP. The other include directive uses a different type of syntax, similar to the XML syntax you have seen already. It has this form: <jsp:include page="header.txt" /> This directive includes the header.txt file, but only at runtime. The JSP compiler does not parse or otherwise interact with this file. The entire contents of the file are included in the output stream for the JSP without being interpreted at all on the Web server. The last directive is taglib . We will cover tag libraries later in this chapter. |