Servlet
Hi there, todaly let's talk about Servlet in a nutshell.
A Servlet is a Java programming language class, which is executed in Web Server and responsible for dynamic content generation in a portable way.
Servlet extends the capabilities of servers that host applications accessed by means of a request-response programming model.
This blog talks about several topics, shown below:
mindmap
root(Servlet)
Life Cycle
Configuration
Request and Response
Cookies and Sessions
Event Listener and Filter
But first, let's talk about the hierarchy of Servlet:
The javax.servlet
and javax.servlet.http
packages provide interfaces and classes for writing servlets.
javax.servlet
is a generic interface, and the javax.servlet.http.HttpServlet
is an extension of that interface – adding HTTP specific support – such as doGet
and doPost
.
When it comes to writing a Servlet, we usually choose to extend HttpServlet
and override doGet
and doPost
.
Life Cycle
The web container maintains the life cycle of a servlet instance:
-
Load
when the first request is received, Web Container loads the servlet class and initialize an instance
-
Initialize
The web container then creates one single servlet instance, to handle all incoming requests on that servlet, even there are concurrent requests.
-
init()
The web container calls the
init()
method only once after creating the servlet instance, to initialize the servlet. -
service()
For every request, servlet creates a separate thread to execute
service()
-
destoy()
The web container asks servlet to release all the resources associated with it, before removing the servlet instance from the service.
A typical Servlet demo:
snippet of web.xml
:
1<?xml version="1.0" encoding="UTF-8"?>
2<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
5 id="WebApp_ID" version="3.0">
6
7 <servlet>
8 <servlet-name>ServletLifecycle</servlet-name>
9 <servlet-class>ServletLifecycleExample</servlet-class>
10 </servlet>
11
12 <servlet-mapping>
13 <servlet-name>ServletLifecycle</servlet-name>
14 <url-pattern>/</url-pattern>
15 </servlet-mapping>
16</web-app>
snippet of index.jsp
:
1<%@ page language="java"
2 contentType="text/html; charset=ISO-8859-1"
3 pageEncoding="ISO-8859-1"%>
4<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5<html>
6<head>
7 <title>Servlet Lifecycle Example</title>
8</head>
9<body>
10 <form action="ServletLifecycle" method="post">
11 <input type="submit" value="Make request" />
12 </form>
13</body>
14</html>
snippet of ServletLifecycleExample.java
:
1import java.io.IOException;
2import java.io.PrintWriter;
3
4import javax.servlet.GenericServlet;
5import javax.servlet.ServletException;
6import javax.servlet.ServletRequest;
7import javax.servlet.ServletResponse;
8
9public class ServletLifecycleExample extends GenericServlet {
10
11 @Override
12 public void init() {
13 System.out.println("Servlet Initialized!");
14 }
15
16 @Override
17 public void service(ServletRequest request, ServletResponse response)
18 throws ServletException, IOException {
19 response.setContentType("text/html");
20 PrintWriter out = response.getWriter();
21 out.println("Servlet called from jsp page!");
22 }
23
24 @Override
25 public void destroy() {
26 }
27}
Servlet life time shown in the sequence chart below:
sequenceDiagram
participant Browser
participant Server
participant Servlet
autonumber
Browser->>Server: Connect to the server
Browser->>Server: HTTP GET
Server->>Server: Resolve
Server->>Servlet: Load Servlet and create obj for first access
Server->>Servlet: invoke `init()`
Server->>Servlet: invoke `service()`
Servlet->>Servlet: Execute `service()` and generate Response
Servlet-->>Server: Response
Server-->>Browser: Response
Configuration
Tomcat
Tomcat is a servlet container, which is a runtime shell that manages and invokes servlets on behalf of users.
Tomcat has the following directory structure:
Directory | Description |
---|---|
bin | startup/shutdown... scripts |
conf | configuration files including server.xml (Tomcat's global configuration file) and web.xml (sets the default values for web applications deployed in Tomcat) |
doc | documents regarding Tomcat |
lib | various jar files that are used by Tomcat |
logs | log files |
src | servlet APIs source files, and these are only the empty interfaces and abstract classes that should be implemented by any servlet container |
webapps | sample web applications |
work | intermediate files, automatically generated by Tomcat |
classes | to add additional classes to Tomcat's classpath |
Note:
-
The single most important directory is webapps, where we can manually add our Servlet into it, e.g., if we want to create a servlet named
HelloServlet
, the first thing we do is to create the directory/webapps/HelloServlet
. -
The default port for Tomcat is 8080, and if we want to switch the port to 80, we just need to modify
/conf/server.xml
:1 <Connector port="80" protocol="HTTP/1.1" 2 connectionTimeout="20000" 3 redirectPort="8443" />
web.xml
To deploy servlets and map URLs to the servlets, we have to modify the web.xml
file, a deployment descriptor, like this:
1<web-app>
2 <servlet>
3 <servlet-name>servletName</servlet-name>
4 <servlet-class>servletClass</servlet-class>
5 </servlet>
6 <servlet-mapping>
7 <servlet-name>servletName</servlet-name>
8 <url-pattern>*.*</url-pattern>
9 </servlet-mapping>
10</web-app>
When a request comes, it is matched with URL pattern in servlet mapping attribute.
When URL matched with URL pattern, Web Server try to find the servlet name in servlet attributes, same as in servlet mapping attribute.
When match found, control goes to the associated servlet class.
ServletConfig
ServletConfig
, a servlet configuration object used by a servlet container to pass information to a servlet during initialization.
<init-param>
attribute is used to define a init parameter, which refers to the initialization parameters of a servlet or filter. <init-param>
attribute has 2 main sub attributes: <param-name>
and <param-value>
. The <param-name>
contains the name of the parameter and <param-value>
contains the value of the parameter.
Example:
snippet of web.xml
:
1<init-param>
2 <param-name>appUser</param-name>
3 <param-value>jai</param-value>
4</init-param>
snippet of InitParamExample.java
:
1ServletConfig config = getServletConfig();
2String appUser = config.getInitParameter("appUser");
This example shows how to read web.xml
, and get init parameters "appUser": "jai"
for initialization.
ServletContext
ServletContext
defines a set of methods that a servlet will use to communicate with its servlet container, to share initial parameters or configuration information to the whole application.
<context-param>
attribute is used to define a context parameter, which refers to the initialization parameters for all servlets of an application. <context-param>
attribute also has 2 main sub attributes: <param-name>
and <param-value>
. And also, the <param-name>
contains the name of the parameter, the <param-value>
contains the value of the parameter.
Example:
snippet of web.xml
:
1<context-param>
2 <param-name>appUser</param-name>
3 <param-value>jai</param-value>
4</context-param>
snippet of ContextParamExample.java
:
1ServletContext context = this.getServletContext();
2String value = (String) context.getAttribute("appUser");
This example shows how to read web.xml
, and get context parameters "appUser": "jai"
for communication.
load-on-startup
The load-on-startup
is the sub attribute of servlet attribute in web.xml
. It is used to control when the web server loads the servlet.
As we discussed that servlet is loaded at the time of first request. In this case, response time is increased for first request.
If load-on-startup
is specified for a servlet in web.xml
, then this servlet will be loaded when the server starts. So the response time will NOT increase for fist request.
Example:
1<servlet>
2 <servlet-name>servlet1</servlet-name>
3 <servlet-class>com.w3spoint.business.Servlet1 </servlet-class>
4 <load-on-startup>0</load-on-startup>
5</servlet>
6
7<servlet>
8 <servlet-name>servlet2</servlet-name>
9 <servlet-class> com.w3spoint.business.Servlet2</servlet-class>
10 <load-on-startup>1</load-on-startup>
11</servlet>
12
13<servlet>
14 <servlet-name>servlet3</servlet-name>
15 <servlet-class> com.w3spoint.business.Servlet3</servlet-class>
16 <load-on-startup>-1</load-on-startup>
17</servlet>
In the example above, Servlet1 and Servlet2 will be loaded when server starts because non-negative value is passed in there load-on-startup
. While Servlet3 will be loaded at the time of first request because negative value is passed in there load-on-startup
.
Request and Response
There is a method named service()
in package javax.servlet
, as is mentioned in the 'Life Cycle' section, it has a prototype like this:
1void service(ServletRequest request,
2 ServletResponse response)
3 throws ServletException,
4 IOException
where request
is the ServletRequest
object that contains the client's request, and response
is the ServletResponse
object that contains the servlet's response
ServletRequest
ServletRequest
defines an object to provide client request information to a servlet.
The servlet container creates a ServletRequest
object and passes it as an argument to the servlet's service()
method. A ServletRequest
object provides data including parameter name and values, attributes, and an input stream.
To transfer data to other component, we can use getAttribute()
, setAttribute()
of ServletRequest
, example code:
1@WebServlet(name = "LoginServlet", urlPatterns = {"/login.do"})
2public class LoginServlet extends HttpServlet {
3 public void doPost(HttpServletRequest request,
4 HttpServletResponse response)
5 throws ServletException, IOException {
6 String username = request.getParameter("username");
7 String password = request.getParameter("password");
8 if (username.equals("admin") &&
9 password.equals("5F4DCC3B5AA765D61D8327DEB882CF99")) {
10 // Logged in
11 RequestDispatcher rd =
12 request.getRequestDispatcher("/welcome.jsp");
13 // to store `username` in request object
14 request.setAttribute("user", username);
15 rd.forward(request, response);
16 } else {
17 // Failed to log in
18 RequestDispatcher rd =
19 request.getRequestDispatcher("/login.jsp");
20 rd.forward(request, response);
21 }
22
23 }
24}
HttpServletRequest
HttpServletRequest
interface adds the methods that relates to the HTTP protocol.
classDiagram
class ServletRequest {
+getAttribute()
+getParameter()
}
class HttpServletRequest {
+getMethod()
+getSession()
}
ServletRequest <|-- HttpServletRequest: extends
(Note: could not display <<interface>>
for both classes, due to error of Mermaid version 9.4.3 , maybe the Mermaid-js team will fix this issue later)
The servlet container creates an HttpServletRequest
object and passes it as an argument to the servlet's service()
methods (doGet()
, doPost()
, etc).
Demo of HttpServletRequest
:
snippet of index.html
:
1<form method="post" action="check">
2 Name <input type="text" name="user" >
3 <input type="submit" value="submit">
4</form>
snippet of web.xml
:
1<servlet>
2 <servlet-name>check</servlet-name>
3 <servlet-class>MyHttpServletRequestServlet</servlet-class>
4</servlet>
5<servlet-mapping>
6 <servlet-name>check</servlet-name>
7 <url-pattern>/check</url-pattern>
8</servlet-mapping>
snippet of MyHttpServletRequestServlet.java
:
1import java.io.*;
2import javax.servlet.*;
3import javax.servlet.http.*;
4
5public class MyHttpServletRequestServlet extends HttpServlet {
6
7 protected void doPost(HttpServletRequest request,
8 HttpServletResponse response)
9 throws ServletException, IOException {
10 response.setContentType("text/html;charset=UTF-8");
11 PrintWriter out = response.getWriter();
12 try {
13 String user = request.getParameter("user");
14 out.println("<h2> Welcome "+user+"</h2>");
15 } finally {
16 out.close();
17 }
18 }
19}
RequestDispatcher
RequestDispatcher
defines an object that receives requests from the client and sends them to any resource (such as a servlet, HTML file, or JSP file) on the server.
The servlet container creates the RequestDispatcher
object, which is used as a wrapper around a server resource located at a particular path or given by a particular name.
Methods of RequestDispacher
interface:
1public void forward(ServletRequest request,
2 ServletResponse response)
3 throws ServletException, IOException
4
5public void include(ServletRequest request,
6 ServletResponse response)
7 throws ServletException, IOException
To get an object of RequestDispacher
:
RequestDispacher
object can be gets from HttpServletRequest
object.
ServletRequest
’s getRequestDispatcher()
method is used to get RequestDispatcher
object.
Example:
1protected void doPost(HttpServletRequest request,
2 HttpServletResponse response)
3 throws ServletException, IOException {
4 response.setContentType("text/html");
5 PrintWriter out = response.getWriter();
6
7 //get parameters from request object.
8 String userName =
9 request.getParameter("userName").trim();
10 String password =
11 request.getParameter("password").trim();
12
13 //check for null and empty values.
14 if(userName == null || userName.equals("")
15 || password == null || password.equals("")){
16 out.print("Please enter both username" +
17 " and password. <br/><br/>");
18 RequestDispatcher requestDispatcher =
19 request.getRequestDispatcher("/login.html");
20 requestDispatcher.include(request, response);
21 }//Check for valid username and password.
22 else if(userName.equals("jai") &&
23 password.equals("1234")){
24 RequestDispatcher requestDispatcher =
25 request.getRequestDispatcher("WelcomeServlet");
26 requestDispatcher.forward(request, response);
27 }else{
28 out.print("Wrong username or password. <br/><br/>");
29 RequestDispatcher requestDispatcher =
30 request.getRequestDispatcher("/login.html");
31 requestDispatcher.include(request, response);
32 }
33}
In brief:
1// 1. use `requestDispatcher.include()`:
2// if invalid `userName` or `password` inputed,
3// return to 'login.html' and retry
4RequestDispatcher requestDispatcher =
5 request.getRequestDispatcher("/login.html");
6requestDispatcher.include(request, response);
7
8// 2. use `requestDispatcher.forward()`:
9// if correct `userName` and `password` inputed,
10// return to 'Welcome Servlet'
11RequestDispatcher requestDispatcher =
12 request.getRequestDispatcher("WelcomeServlet");
13requestDispatcher.forward(request, response);
ServletResponse
ServletResponse
defines an object to assist a servlet in sending a response to the client.
The servlet container creates a ServletResponse
object and passes it as an argument to the servlet's service()
method. To send binary data in a MIME body response, use the ServletOutputStream
returned by getOutputStream()
. To send character data, use the PrintWriter
object returned by getWriter()
. To mix binary and text data, for example, to create a multipart response, use a ServletOutputStream
and manage the character sections manually.
HttpServletResponse
HttpServletResponse
extends the ServletResponse
interface to provide HTTP-specific functionality in sending a response. For example, it has methods to access HTTP headers and cookies.
The servlet container creates an HttpServletResponse
object and passes it as an argument to the servlet's service()
methods (doGet()
, doPost()
, etc).
Cookies and Sessions
There are 2 mechanisms which allow us to store user data between subsequent requests to the server – the cookie and the session
Cookie
A cookie is a small piece of information as a text file stored on client’s machine by a web application.
The servlet sends cookies to the browser by using the HttpServletResponse.addCookie(javax.servlet.http.Cookie)
method, which adds fields to HTTP response headers to send cookies to the browser, one at a time. The browser is expected to support 20 cookies for each Web server, 300 cookies total, and may limit cookie size to 4 KB each.
The browser returns cookies to the servlet by adding fields to HTTP request headers. Cookies can be retrieved from a request by using the HttpServletRequest.getCookies()
method. Several cookies might have the same name but different path attributes.
There are 2 types of cookies:
-
Session cookies (Non-persistent cookies) They are accessible as long as session is open, and they are lost when session is closed by exiting from the web application.
-
Permanent cookies(Persistent cookies) They are still alive when session is closed by exiting from the web application, and they are lost when they expire.
Example:
1//create cookie object
2Cookie cookie=new Cookie(“cookieName”,”cookieValue”);
3response.addCookie(cookie);
4
5//get all cookie objects.
6Cookie[] cookies = request.getCookies();
7for(Cookie cookie : cookies){
8 out.println(“Cookie Name: ” + cookie.getName());
9 out.println(“Cookie Value: ” + cookie.getValue());
10}
11
12//Remove value from cookie
13Cookie cookie = new Cookie(“cookieName”, “”);
14cookie.setMaxAge(0);
15response.addCookie(cookie);
HttpSession
HttpSession
is an interface that provides a way to identify a user in multiple page requests. A unique session id is given to the user when first request comes. This id is stored in a request parameter or in a cookie.
Example:
1HttpSession session = request.getSession();
2session.setAttribute("attName", "attValue");
3String value = (String) session.getAttribute("attName");
Filter and Event Listener
In web applications, we use filters to preprocess and postprocess the parameters. And during runtime of web apps, we use event listeners to do callback stuff.
Filter
A filter is an object that is invoked at the preprocessing and postprocessing of a request on the server.
Servlet filters are mainly used for following tasks:
-
Preprocessing
Preprocessing of request before it accesses any resource at server side.
-
Postprocessing
Postprocessing of response before it sent back to client.
flowchart TD
Client <--> Listener[Web<br/>Listener]
Listener <--> Container[Servlet Container]
Container --> |Request| Filter1 --> Filter2 --> FilterN --> Servlet
Servlet --> |Response| FilterN --> Filter2 --> Filter1 --> Container
The order in which filters are invoked depends on the order in which they are configured in the web.xml
file. The first filter in web.xml
is the first one invoked during the request, and the last filter in web.xml
is the first one invoked during the response. Note the reverse order during the response.
Filter
API (or interface) includes some methods which help us in filtering requests:
1public void init(FilterConfig config)
2public void doFilter(HttpServletRequest request,HttpServletResponse response, FilterChain chain)
3public void destroy()
To create a filter, implement javax.servlet.Filter
interface
<filter>
attribute is used to define a filter in web.xml
:
1<filter>
2 <filter-name>filterName </filter-name>
3 <filter-class>filterClass</filter-class>
4</filter>
5<filter-mapping>
6 <filter-name>filterName</filter-name>
7 <url-pattern>urlPattern</url-pattern>
8</filter-mapping>
FilterChain
object is used to call the next filter or a resource, if it is the last filter in filter chaining.
Example:
snippet of MyFilter.java
:
1public class MyFilter implements Filter {
2
3 public void init(FilterConfig filterConfig) throws ServletException { }
4
5 @Override
6 public void doFilter(ServletRequest request,
7 ServletResponse response,
8 FilterChain chain)
9 throws IOException, ServletException
10 {
11
12 PrintWriter out = response.getWriter();
13 System.out.println("preprocessing before servlet");
14 // pass to next filter for more check
15 chain.doFilter(request, response);
16 System.out.println("postProcessing after servlet");
17 }
18
19 public void destroy() {}
20}
21
snippet of index.html
:
1<form action="MyFilterServlet">
2 <button type="submit">Click here to go to the Servlet</button>
3</form>
1<?xml version="1.0" encoding="UTF-8"?>
2<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xmlns="http://xmlns.jcp.org/xml/ns/javaee"
4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
5 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
6 id="WebApp_ID" version="4.0">
7<display-name>MyFilterServlet</display-name>
8<welcome-file-list>
9 <welcome-file>index.html</welcome-file>
10</welcome-file-list>
11
12<filter>
13 <filter-name>filter1</filter-name>
14 <filter-class>com.app.MyFilterServlet</filter-class>
15</filter>
16
17<filter-mapping>
18 <filter-name>filter1</filter-name>
19 <url-pattern>/MyFilterServlet</url-pattern>
20</filter-mapping>
21
22</web-app>
23
snippet of MyFilterServlet.java
:
1@WebServlet("/MyFilterServlet")
2public class MyFilterServlet extends HttpServlet {
3
4 protected void doGet(HttpServletRequest request,
5 HttpServletResponse response)
6 throws ServletException, IOException
7 {
8 PrintWriter out = response.getWriter();
9 out.println("<h1>Welcome to the Servlet.");
10 System.out.println("MyFilterServlet is running");
11 }
12
13 protected void doPost(HttpServletRequest request,
14 HttpServletResponse response)
15 throws ServletException, IOException
16 {
17 doGet(request, response);
18 }
19}
Event Listener
Event Listener allows Servlet to track key events in your Web applications through event listeners.
This functionality allows more efficient resource management and automated processing based on event status.
flowchart TD
Client <--> Listener[Web<br/>Listener]
Listener <--> Container[Servlet Container]
Container --> |Request| Servlet
Servlet --> |Response| Container
There are 2 levels of servlet events:
-
Servlet context-level (application-level) event
This event involves resources or state held at the level of the application servlet context object.
-
Session-level event
This event involves resources or state associated with the series of requests from a single user session; that is, associated with the HTTP session object.
Listeners handling Servlet Lifecycle Events:
Object: Event | Listener Interface | Event Class |
---|---|---|
Web context: Initialization and destruction | ServletContextListener |
ServletContextEvent |
Web context: Attribute added, removed, or replaced | ServletContextAttributeListener |
ServletContextAttributeEvent |
Session: Creation, invalidation, activation, passivation, and timeout | HttpSessionListener , HttpSessionActivationListener |
HttpSessionEvent |
Session: Attribute added, removed, or replaced | HttpSessionAttributeListener |
HttpSessionBindingEvent |
Request: A servlet request has started being processed by web components | ServletRequestListener |
ServletRequestEvent |
Request: Attribute added, removed, or replaced | ServletRequestAttributeListener |
ServletRequestAttributeEvent |
Event classes:
Event Class | Methods |
---|---|
ServletRequestEvent | getServletContext() , getServletRequest() |
ServletContextEvent | getServletContext() |
ServletRequestAttributeEvent | getName() , getValue() |
ServletContextAttributeEvent | getName() , getValue() |
HttpSessionEvent | sessionCreated() , sessionDestroyed() , sessionWillPassivate() , sessionDidActivate() |
HttpSessionBindingEvent | getName() , getSession() , getValue() |
Configure the Listener class in the web.xml
files:
1<web-app>
2 <listener>
3 <listener-class>myListenerName</listener-class>
4 </listener>
5</web-app>
Note: Except for HttpSessionBindingListener
and HttpSessionActivationListener
, all Listeners require the aforementioned listener configuration.
Example Code of AppContextAttributeListener
:
snippet of web.xml
:
1<listener>
2 <listener-class>AppContextAttributeListener</listener-class>
3</listener>
snippet of AppContextAttributeListener.java
:
1@WebListener
2public class AppContextAttributeListener implements ServletContextAttributeListener {
3 public void attributeAdded(ServletContextAttributeEvent event) {
4 System.out.println( "ServletContext attribute added::{" event.getName() + ","+ event.getValue() + "}");
5 }
6
7 public void attributeReplaced(ServletContextAttributeEvent event) {
8 System.out.println( "ServletContext attribute replaced::{" event.getName() + ","+ event.getValue() + "}");
9 }
10 public void attributeRemoved(ServletContextAttributeEvent event) {
11
12 System.out.println( "ServletContext attribute removed::{" event.getName() + ","+ event.getValue() + "}");
13 }
14}