Servlets
Goal
- Understand the Java EE Servlet API.
- Learn more about HTTP:
- The HTTP
Content-Type
header. - HTTP redirects.
- The HTTP
HEAD
method.
- The HTTP
- Write simple HTTP servlets supporting GET, HEAD, content types, and redirects.
Concepts
- Common Gateway Interface (CGI)
- deployment descriptor
- Hypertext Transfer Protocol (HTTP)
- Java Platform, Enterprise Edition (Java EE)
- Postman
- redirect
- servlet
- servlet container
- Tomcat
- World Wide Web (WWW)
Library
javax.servlet.http.HttpServlet
javax.servlet.http.HttpServlet.doGet(HttpServletRequest req, HttpServletResponse resp)
javax.servlet.http.HttpServletRequest
javax.servlet.http.HttpServletRequest.getRequestURI()
javax.servlet.http.HttpServletResponse
javax.servlet.http.HttpServletResponse.SC_OK
javax.servlet.http.HttpServletResponse.NOT_FOUND
javax.servlet.
HttpServletResponse.sendRedirect(String location)javax.servlet.http.HttpServletResponse.setStatus(int sc)
javax.servlet.Servlet
javax.servlet.Servlet.init(ServletConfig config)
javax.servlet.Servlet.service(ServletRequest req, ServletResponse res)
javax.servlet.ServletRequest
javax.servlet.ServletResponse
javax.servlet.ServletResponse.getOutputStream()
javax.servlet.ServletResponse.getWriter()
javax.servlet.ServletResponse.setCharacterEncoding(String charset)
javax.servlet.ServletResponse.setContentType(String type)
javax.servlet.annotation.WebServlet
Dependencies
javax:javaee-api:7.0
(scope: provided)
Preview
Preparation
- Download and install the latest Apache Tomcat 8.5.
- Download the source code JAR separately so that you can attach it to Eclipse for viewing servlet source code.
- Install the Postman Chrome app.
Lesson
As you've discovered in previous lessons, the most prevalent TCP/IP application-level protocol is the Hypertext Transfer Protocol (HTTP). The basic HTTP transaction consists of a request followed by a response. You've written HTTP client code that makes a request using the HTTP GET
method and processed the response using JSON.
For client software to communicate using HTTP, there must be a server software component listening for HTTP requests and sending appropriate responses. Traditionally an HTTP server was simply a program that would return static HTML documents in response to GET
requests; this formed the basis of the original World Wide Web (WWW). As the web evolved, HTTP servers allowed requests to be handed off for processing by separate executable programs. This allowed the generation of dynamic content and was referred to as a Common Gateway Interface (CGI).
CGI scripts had a central drawback in that each time a request came in the web server would be required to spawn a new execution environment for the CGI program. To address this performance hit, Java introduced the servlet specification. Rather than starting a new JVM to service each HTTP request, a web server can now keep a single JVM loaded in memory and make calls to Java code to process incoming HTTP requests. The servlet specification has continued to evolve and is now distributed as part of the Java Platform, Enterprise Edition (Java EE).
Servlets
Most Java HTTP technologies today are based upon servlets at their core. Servlet technology centers around an implementation of the javax.servlet.Servlet
interface. A servlet container on the server will create an instance of the servlet implementation as needed and pass HTTP requests to it for processing. Writing a servlet then consists of providing an implementation of the Servlet
interface and registering it with the servlet container.
Here is the basic Servlet
interface. Its Servlet.service(ServletRequest req, ServletResponse res)
method is the primary doorway for servicing client requests, represented by javax.servlet.ServletRequest
, and returning the appropriate response, represented by javax.servlet.ServletResponse
.
Servlet Life Cycle
Like many objects that are managed by containers, servlets go through a life cycle analogous to the states of a thread which you studied in a previous lesson. The container will notify the servlet as it passes through these simple stages by calling the appropriate life cycle method in the servlet interface.
- The container creates the servlet.
- The container initializes the servlet by calling
Servlet.init(ServletConfig config)
. - The servlet processes client requests as needed in its
Servlet.service(ServletRequest req, ServletResponse res)
method. - The container takes the servlet out of service and calls its
Servlet.destroy()
method.
Servicing HTTP Requests
Classes can use the Servlet
interface to implement any network protocol that uses a request/response pattern. But to service HTTP requests specifically, it is usually best to extend the javax.servlet.http.HttpServlet
abstract class.
The HttpServlet
base class overrides the Servlet.service(…)
method to provide basic dispatching based on the HTTP method used. A separate Servlet.doXXX(…)
method is provided for each HTTP method. You have already worked with the HTTP GET
method. The other methods available in the HttpServlet
base class should give you an idea of the HTTP methods that exist.
HTTP GET
Method
To process the GET
HTTP method, override the HttpServlet.doGet(HttpServletRequest req, HttpServletResponse resp)
method and return the appropriate content. As with the more general Servlet.service(…)
method, the method parameters encapsulate the client's request and the servlet's response. javax.servlet.http.HttpServletRequest
extends ServletRequest
, while javax.servlet.http.HttpServletResponse
extends ServletResponse
, providing access to HTTP-specific information.
Returning Response Content
To send back response content bytes, you can use the ServletResponse.getOutputStream()
method of the response. If you specifically want to return text content, you can use ServletResponse.getWriter()
instead. Before retrieving a Writer
, you need to first call ServletResponse.setCharacterEncoding(String charset)
with the name of the appropriate charset so that the ServletResponse
knows how to convert the characters to bytes to send back to the client.
Here is an implementation of a servlet that would be send back the text Hello, World!
in response to an HTTP GET
request.
HTTP Content-Type
Header
In your response you will need to indicate the media type of the content you are returning. You briefly saw the use of HTTP headers when first learning Internet protocols. HTTP uses the response header Content-Type
to indicate the media type of the content being returned.
You indicate the content type of a servlet response by calling ServletResponse.setContentType(String type)
before producing content. This allows the servlet to include the Content-Type
header when the response is generated.
Setting the Response Code
A successful HTTP request will send back a status code of 200
(OK
), and this is what HttpServlet.doGet(…)
sends back by default. If you wish to send back another code such as 404
(Not Found
), you may call HttpServletResponse.setStatus(int sc)
. The HttpServletResponse
class provides constants for status codes such as HttpServletResponse.SC_OK
and HttpServletResponse.NOT_FOUND
; when writing servlets, it is best to use these rather than those in java.net.HttpURLConnection
.
Declaring a Servlet
A servlet cannot function until it has been recognized by the servlet container, which will create and initialize, a servlet instance. The container also needs to know which requests the servlet should service. This is done by mapping some relative URI path to the servlet. The javax.servlet.annotation.WebServlet
annotation provides a simple way to indicate the URL path at which the servlet should service HTTP requests in the servlet container.
Here is an implementation of a Hello World
servlet that would be registered to process HTTP GET
requests sent to the helloworld
path segment in some URL.
HTTP Redirects
You've already learned that the 200
(OK
) response is the most common HTTP code for indicating success. HTTP response codes are divided into categories, and the 2XX
codes all indicate success of the requested operation. The 404
(Not Found
) response code is one of the 4xx
codes representing client-related errors.
The 3XX
response codes indicate that the HTTP request should be redirected, or performed again at another URL. In particular there is the permanent redirect 301
(Moved Permanently
) and the temporary redirect 302
(Found
). The former might be used if you have moved some content to another location but still want old links to work; the HTTP client should know to follow the 301
response and find the content at its new location. The temporary redirect 302
indicates that an item has temporarily been moved to another location. With either type of redirect, the Location
header must indicate the new URL of the moved content.
HTTP HEAD
Method
The HTTP HEAD
method functions virtually identically to the GET
method, except that it only returns the headers (not the content) of the HTTP response that would normally be sent in response to a GET
request. The base HttpServlet
implementation provides a default implementation for handling of the HEAD
request, using the headers from the HttpServlet.doGet(…)
implementation.
Tomcat
Apache Tomcat® is an J2EE compliant open-source server written in Java and that implements the servlet API. It easily integrates into Eclipse. To install it, simply download the appropriate compressed archive and extract the files to the desired program location.
Installation
- Download the latest Tomcat 8.5.x from Tomcat 8 Software Downloads. Linux users will usually download the
.tar.gz
archive, while Windows users will probably want to get the.zip
archive.- Download the Core package under Binary Distributions.
- (optional)Download the archive under Source Code Distributions.
- Extract the archive to the directory of your choice. Linux users may prefer
/opt/tomcat
, while Windows users may want to useC:\Program Files\Tomcat
.
Running Tomcat Standalone
TODO
Eclipse
The Eclipse environment makes it easy for you to run an embedded Tomcat instance and deploy a servlet class in the Tomcat servlet container.
- Configure the a runtime environment for your Tomcat installation.
- Go to Window → Preferences → Server → Runtime Environment.
- Select Add... and choose Apache Tomcat v8.5; then select Next >.
- Enter the directory where you extracted Tomcat, or find the directory using Browse....
- Select Finish and then OK.
- Add a configured server and deploy your servlet.
- by going to Window → Show View → Other..., selecting Servers → Servers, and selecting OK. Thiswill bring up the Servers view tab.
- In the
Servers
view click the link for creating a new server, or Right-Click → New → Server. - Leave the server's name as
localhost
, which the hostname indicating the computer you're running on. - Click Next, select your project in the Available list, and then Add to add your project to the Configured panel. This deploys your servlet to the configured Tomcat instance.
- Select Finish.
You can now start and stop the server from the Servers view. By default the server will be listening on port 8080
.
Postman
Google's Postman Chrome app is invaluable for testing and debugging HTTP applications. In its simplest configuration it performs a function similar a browser, issuing an HTTP GET
request and displaying the response. But Postman also knows how to issue a variety of HTTP requests, including the HEAD
method you learned about in this lesson, and allows in-depth exploration of the details of requests and responses. You can find complete instructional videos on using Postman in the See Also section below.
Review
Summary
Assume that a servlet container is configured to service the /foo/*
path on the localhost
machine on port 8080
, and that com.example.FooBarServlet
extends the HttpServlet
class and has an annotation @WebServlet("/bar")
.
- The user enters
http://locahost:8080/foo/bar
into the browser. - The Tomcat server recognizes that the request is for
http://locahost:8080/foo/*
and routes it to the servlet container. - The servlet container looks at the ending
/bar
and sees that this is mapped toFooBarServlet
. - The servlet container passes the request to
FooBarServlet.service(ServletRequest req, ServletResponse res)
. - The default
Servlet.service(ServletRequest req, ServletResponse res)
implementation determines that this is aGET
request and delegates toHttpServlet.doGet(HttpServletRequest req, HttpServletResponse resp)
. - The
FooBarServlet
has overriddendoGet(…)
and returns the appropriate response forhttp://locahost:8080/foo/bar
.
Gotchas
- Don't forget to call
ServletResponse.setCharacterEncoding(String charset)
before callingServletResponse.getWriter()
, or the returned writer will use the limitedISO-8859-1
charset. - If you wrap the ServletResponse OutputStream or Writer with a buffered version, don't forget to flush the buffered version after you are finished writing, or the written bytes or characters may not be written to the underlying stream and never make it back to the client.
In the Real World
The decision to use a 301
(Moved Permanently
) or a 302
(Found
) redirect can have implications on how your web page is indexed by search engines. If you use a permanent redirect, the search engine may store the redirected URL in its index and provide that address as the official URL of your site. (If your site continues to use a temporary redirect, Google may nevertheless eventually consider it to be permanent, so the distinction between the two can be complicated in practice. See Google: We May Make Your 302 Temporary Redirects As 301 Permanent Redirects.)
Think About It
The servlet specification allows a single servlet to be mapped to an entire tree of paths, using e.g. @WebServlet("/vehicles/*")
. This single servlet could therefore service requests for all vehicle URIs such as …/vehicles/new/12345
, looking up vehicle information in a database and generating a JSON document or even an HTML web page dynamically. To the web browser client it would appear as if an HTML file was being retrieved for each vehicle, but in reality no web pages would exist on the file system—they would be produced on-the-fly as needed by a single servlet, based upon the incoming request URI.
Self Evaluation
- What benefit did servlets bring over previous technologies?
- What is the conceptual difference between a server and a servlet container?
- What is the difference semantically between a temporary and a permanent redirect?
- What is a
web.xml
deployment descriptor? Do you need one of those? Why or why not? - How could you debug a servlet inside Eclipse?
Task
Create a Booker server and test it.
- Create a separate package named
….booker.server
. For now you can keep everything in the samebooker
project. - Create a
BookerServlet
that will return the plain text string"booker"
when accessinghttp://localhost:8080/booker/application
using the HTTPGET
method.- Verify using Postman that an HTTP
GET
request tohttp://localhost:8080/booker/application
will return the correct content type and content. - Verify using Postman that an HTTP
HEAD
request tohttp://localhost:8080/booker/application
will return the correct headers but no content.
- Verify using Postman that an HTTP
- Create another servlet that will redirect HTTP
GET
requests forhttp://localhost:8080/booker/app
tohttp://localhost:8080/booker/application
. Which type of redirect should you use?- Verify using Postman that an HTTP
HEAD
request tohttp://localhost:8080/booker/app
will be redirected correctly.
- Verify using Postman that an HTTP
See Also
- Java Servlet Technology (Oracle - The Java EE Tutorial)
- About Servlets (Stack Overflow)
- How to create, deploy and run Java Servlet in Eclipse (CodeJava)
- How to Install Apache Tomcat 8 (on Windows, Mac OS X, Ubuntu) and Get Started with Java Servlet Programming (Chua Hock-Chuan)
- Postman How-to Series (Postman - YouTube)
References
- RFC 7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
- RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
- JSR 340: Java Servlet 3.1 Specification
- Java EE 7 Deployment Descriptors (Antonio's Blog)
Resources
Acknowledgments
Servlet
andHttpServlet
code snippets extracted from source code Copyright (c) 1997-2013 Oracle and/or its affiliates.- Apache Tomcat, Tomcat, Apache, the Apache feather, and the Apache Tomcat project logo are trademarks of the Apache Software Foundation.