B.1. Servlet and JavaServer Pages Overview

Java servlet technology is a means by which to execute Java programs efficiently in a web environment. The Java Servlet Specification defines the conventions of this environment, which may be summarized briefly as follows:

The following listing shows what a simple servlet looks like. It's a Java program that implements a SimpleServlet class. The class has a doGet( ) method to be invoked by the servlet container when it receives a GET request for the servlet. It also has a doPost( ) method to handle the possibility that a POST request may be received instead; it's simply a wrapper that invokes doGet( ). SimpleServlet produces a short HTML page that includes some static text that is the same each time the servlet runs, and two dynamic elements (the current date and client IP address) that vary over time and for each client:

import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class SimpleServlet extends HttpServlet { public void doGet (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { PrintWriter out = response.getWriter ( ); response.setContentType ("text/html"); out.println ("

"); out.println (""); out.println ("Simple Servlet"); out.println (""); out.println ("

"); out.println ("

Hello.

"); out.println ("

The current date is " + new Date ( ) + ".

"); out.println ("

Your IP address is " + request.getRemoteAddr ( ) + ".

"); out.println ("

"); out.println (""); } public void doPost (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { doGet (request, response); } }

As you will no doubt observe, this "simple" servlet really isn't so simple! It requires a fair amount of machinery to import the requisite classes and to establish the doGet( ) and doPost( ) methods that provide the standard interface to the servlet container. Compare the servlet to the following PHP script, which does the same thing in a much more concise fashion:

 

Simple PHP Page

Hello.

The current date is .

Your IP address is .

The contrast between the Java servlet and the PHP script illustrates one of the problems with writing servletsthe amount of repetitious overhead:

The first two points can be addressed by using a prototype file that you copy when beginning a new servlet. The third point (wrapping each line of HTML within a print statement) is not so easily addressed and is possibly the single most tedious aspect of servlet writing. It also leads to another issue: a servlet's code may be easy enough to read as Java, but it's sometimes difficult to discern the structure of the HTML that the code generates. The problem is that you're really trying to write in two languages at once (i.e., you're writing Java that writes HTML), which isn't really optimal for either language.

B.1.1 JSP PagesAn Alternative to Servlets

One of the reasons for the invention of JavaServer Pages was to relieve the burden involved in creating web pages by means of lots of print statements. JSP uses a notational approach that is similar to PHP: HTML is written literally without being wrapped in print statements, and code to be executed is embedded in the page within special markers. The following listing shows a JSP page that is equivalent to the SimpleServlet servlet, but looks much more like the corresponding PHP script:

 

Simple JSP Page

Hello.

The current date is <%= new java.util.Date ( ) %>.

Your IP address is <%= request.getRemoteAddr ( ) %>.

The JSP page is more concise than the servlet in several ways:

When a servlet container receives a request for a JSP page, it treats the page as a template containing literal text plus executable code embedded within special markers. The container produces an output page from the template to send to the client. Literal text from the template is left unmodified, the executable code is replaced by any output that it generates, and the combined result is returned to the client as the response to the request. That's the conceptual view of JSP processing, at least. What really happens when a container processes a JSP request is as follows:

Notationally, JSP pages provide a more natural way to write web pages than do servlets. Operationally, the JSP engine provides the benefits of automatic compilation after the page is installed in the document tree or modified thereafter. When you write a servlet, any changes require recompiling the servlet, unloading the old one, and loading the new one. That can lead to an emphasis on messing with the servlet itself rather than a focus on the servlet's purpose. JSP reverses the emphasis so that you think more about what the page does than about the mechanics of getting it compiled and loaded properly.

The differences between servlets and JSP pages do not imply any necessity of choosing to use only one or the other. Application contexts in a servlet container can include both, and because JSP pages are converted into servlets anyway, they can all intercommunicate.

JSP is similar enough to certain other technologies that it can provide a migration path away from them. For example, the JSP approach is much like that used in Microsoft's Active Server Pages (ASP). However, JSP is vendor and platform neutral, whereas ASP is proprietary. JSP thus provides an attractive alternative technology for anyone looking to move away from ASP.

B.1.2 Custom Actions and Tag Libraries

A servlet looks a lot like a Java program, because that's what it is. The JSP approach encourages a cleaner separation of HTML (presentation) and code, because you need not generate HTML from within Java print statements. On the other hand, JSP doesn't require separation of HTML and code, so it's still possible to end up with lots of embedded Java in a page if you're not careful.

One way to avoid inclusion of literal Java in JSP pages is to use another JSP feature known as custom actions. These take the form of special tags that look a lot like HTML tags (because they are written as XML elements). Custom actions allow tags to be defined that perform tasks on behalf of the page in which they occur. For example, a tag might communicate with a database server to issue a query. Custom actions typically come in groups, which are known as tag libraries and are designed as follows:

Tag libraries make it easier to write entire pages using tag notation rather than switching between tags and Java code. The notation is JSP-like, not Java-like, but the effect of placing a custom tag in a JSP page is like making a method call. This is because a tag reference in a JSP page maps onto a method invocation in the servlet that the page is translated into.

To illustrate the difference between the embedded-Java and tag library approaches, compare two JSP scripts that set up a connection to a MySQL server and display a list of tables in the cookbook database. The first one does so using Java embedded within the page:

<%@ page import="java.sql.*" %>

Tables in cookbook Database

Tables in cookbook database:

<% Connection conn = null; String url = "jdbc:mysql://localhost/cookbook"; String user = "cbuser"; String password = "cbpass"; Class.forName ("com.mysql.jdbc.Driver").newInstance ( ); conn = DriverManager.getConnection (url, user, password); Statement s = conn.createStatement ( ); s.executeQuery ("SHOW TABLES"); ResultSet rs = s.getResultSet ( ); while (rs.next ( )) out.println (rs.getString (1) + "

"); rs.close ( ); s.close ( ); conn.close ( ); %>

The same thing can be done using a tag library, such as the JSP Standard Tag Library (JSTL). JSTL consists of several tag sets grouped by function. Using its core and database tags, the preceding JSP page can be converted as follows to avoid entirely the use of literal Java:

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %>

Tables in cookbook Database

Tables in cookbook database:

SHOW TABLES

The taglib directives identify the TLD files that the page uses and indicate that actions from the corresponding tag sets will be identified by prefixes of c and sql. (In effect, a prefix sets up a namespace for a set of tags.) The tag sets up the parameters for connecting to the MySQL server, issues a query, loops through the result, and adds each table name in the result to the output page. (I'm glossing over details, of course; the JSTL tags are described further in Recipe 16.4.)

If it's likely that you'd connect to the database server the same way from most JSP pages in your application context, a further simplification can be achieved by moving the tag to an include file. If you name the file jstl-mcb-setup.inc and place it in the application's WEB-INF directory,[B] any page within the application context can set up the connection to the MySQL server by accessing the file with an include directive. Modifying the preceding page to use the include file results in a script that looks like this:

[B] By convention, application contexts use their WEB-INF directory for private context-specific information. See Recipe B.3.

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %> <%@ include file="/WEB-INF/jstl-mcb-setup.inc" %>

Tables in cookbook Database

Tables in cookbook database:

SHOW TABLES

You're still using Java when you use a tag library, because tag actions map onto Java class invocations. But the notation follows XML conventions, so it's less like writing program code and more like writing HTML page elements. If your organization produces web content using a "separation of powers" workflow, custom actions allow elements of the page that are produced dynamically to be packaged in a way that is easier for designers and other non-programmers to deal with. They don't have to develop or work directly with the classes that implement tag actions; that's left to the programmers that write the classes that correspond to the tags.

Категории