A Jakarta Servlet is a container-managed Java component that handles requests and writes responses. Lifecycle, mappings, shared instances, sessions, filters, and thread safety define its runtime boundary.
A Servlet is a Java server-side component that handles requests and generates responses. Servlets are mainly used to build dynamic web applications, process forms, create controller layers, manage sessions, return HTML or JSON, and connect browser requests to Java business logic.
A Servlet does not run like a normal main() program. It runs inside a Servlet container, also called a web container. The container receives HTTP requests, maps URLs to Servlets, creates request and response objects, manages the Servlet lifecycle, handles threading, and sends the final response back to the client.
A static HTML page always returns the same content. A Servlet can generate different responses based on request data, logged-in user, database records, form input, headers, cookies, or session state.
| Requirement | How Servlet Helps |
|---|---|
| Process a login form | Reads username and password from the request. |
| Show user-specific content | Uses session data or database records. |
| Return JSON for an API | Sets response type and writes JSON output. |
| Upload a file | Reads multipart request data. |
| Protect pages | Works with filters, sessions, and authentication logic. |
| Connect to a database | Calls service/DAO classes and returns results. |
The Servlet container is the runtime environment for Servlets. It sits between the web server and your Java code. Apache Tomcat is one of the most common Servlet containers for learning and deployment.
| Container Responsibility | Description |
|---|---|
| URL mapping | Finds which Servlet should handle a request. |
| Lifecycle management | Loads, initializes, calls, and destroys Servlet instances. |
| Thread management | Allows one Servlet instance to serve many requests concurrently. |
| Request/response creation | Provides HttpServletRequest and HttpServletResponse. |
| Session management | Tracks users across requests with HttpSession. |
| Deployment | Loads WAR files and web application configuration. |
When a browser or API client sends a request, the container follows a clear request-processing flow.
The Servlet API defines the contracts and classes used by Servlet applications. For HTTP web applications, HttpServlet is the most important base class.
| Type | Purpose |
|---|---|
| Servlet | Core interface that defines init(), service(), and destroy(). |
| GenericServlet | Protocol-independent abstract class. |
| HttpServlet | HTTP-specific class with doGet(), doPost(), doPut(), and doDelete(). |
| HttpServletRequest | Represents incoming request data. |
| HttpServletResponse | Represents outgoing response data. |
| HttpSession | Stores user-specific data across requests. |
| ServletContext | Stores application-wide information and resources. |
| ServletConfig | Provides Servlet-specific initialization configuration. |
Older Java EE Servlet applications use jakarta.servlet packages. Newer Jakarta EE applications use jakarta.servlet. The core ideas are the same, but the package names and compatible server versions differ.
| Stack | Package | Common Server | Maven Artifact |
|---|---|---|---|
| Java EE / Servlet 4 | jakarta.servlet | Tomcat 9 | jakarta.servlet-api |
| Jakarta EE / Servlet 5+ | jakarta.servlet | Tomcat 10+ | jakarta.servlet-api |
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
A simple Servlet extends HttpServlet and overrides an HTTP method such as doGet(). The @WebServlet annotation maps the class to a URL.
After deployment, a request such as /hello?name=Asha calls this Servlet and returns an HTML response.
package com.example;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = request.getParameter("name");
if (name == null || name.isBlank()) {
name = "World";
}
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html><body>");
out.println("<h1>Hello, " + name + "!</h1>");
out.println("</body></html>");
}
}
The Servlet container controls the lifecycle. A Servlet is typically created once and reused for many requests. This is important for performance, but it also means you must be careful with shared data.
| Phase | Method | When It Runs |
|---|---|---|
| Loading | Class loading | The container loads the Servlet class. |
| Instantiation | Constructor | The container creates a Servlet object. |
| Initialization | init() | Called once before handling requests. |
| Request handling | service() | Called for each request. |
| HTTP handling | doGet(), doPost() | Called based on HTTP method. |
| Destruction | destroy() | Called once before the Servlet is removed. |
@WebServlet(value = "/status", loadOnStartup = 1)
public class StatusServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("StatusServlet initialized once");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.setContentType("text/plain");
response.getWriter().println("Server is running");
}
@Override
public void destroy() {
System.out.println("StatusServlet destroyed once");
}
}
HttpServlet provides method handlers for common HTTP methods. You override the handler that matches the request type your Servlet should process.
| HTTP Method | Servlet Method | Common Use |
|---|---|---|
| GET | doGet() | Read or display data. |
| POST | doPost() | Submit forms or create data. |
| PUT | doPut() | Update existing data. |
| DELETE | doDelete() | Delete data. |
| HEAD | doHead() | Return headers without body. |
| OPTIONS | doOptions() | Describe supported methods. |
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.sendRedirect("login.html");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String email = request.getParameter("email");
String password = request.getParameter("password");
if ("admin@example.com".equals(email) && "secret".equals(password)) {
response.getWriter().println("Login successful");
} else {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().println("Invalid credentials");
}
}
}
<form action="/login" method="post">
<label for="email">Email</label>
<input id="email" name="email" type="email">
<label for="password">Password</label>
<input id="password" name="password" type="password">
<button type="submit">Login</button>
</form>
HttpServletRequest contains everything the client sent: URL path, parameters, headers, cookies, body data, session reference, and request metadata.
String name = request.getParameter("name");
String method = request.getMethod();
String uri = request.getRequestURI();
String userAgent = request.getHeader("User-Agent");
Cookie[] cookies = request.getCookies();
HttpSession session = request.getSession();
HttpServletResponse controls what the server sends back. You can set content type, status code, headers, cookies, redirects, and response body.
response.setContentType("text/html;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_OK);
PrintWriter out = response.getWriter();
out.println("<h1>Welcome</h1>");
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_OK);
PrintWriter out = response.getWriter();
out.print("{\"status\":\"ok\"}");
A Servlet must be mapped to one or more URL patterns. Mapping can be done with annotations or with web.xml. Annotation mapping is common for simple projects; web.xml is useful for centralized configuration.
@WebServlet(
name = "ProductServlet",
urlPatterns = {"/products", "/products/*"},
loadOnStartup = 1
)
public class ProductServlet extends HttpServlet {
// Servlet code
}
<servlet>
<servlet-name>ProductServlet</servlet-name>
<servlet-class>com.example.ProductServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ProductServlet</servlet-name>
<url-pattern>/products/*</url-pattern>
</servlet-mapping>
ServletConfig stores configuration for one Servlet. ServletContext stores application-wide information shared across the web application.
| Object | Scope | Common Use |
|---|---|---|
| ServletConfig | Single Servlet | Servlet-specific init parameters. |
| ServletContext | Whole web app | Application attributes, resources, logging, shared config. |
String servletValue = getServletConfig().getInitParameter("mode");
ServletContext context = getServletContext();
String appName = context.getInitParameter("appName");
context.setAttribute("totalUsers", 100);
HTTP is stateless, meaning each request is independent. Servlets use HttpSession, cookies, or URL rewriting to remember users across multiple requests.
HttpSession session = request.getSession();
session.setAttribute("userEmail", email);
String userEmail = (String) session.getAttribute("userEmail");
session.invalidate(); // logout
A Servlet instance can handle many requests at the same time using different threads. This means instance variables are shared and can cause bugs if they store request-specific data.
public class UnsafeServlet extends HttpServlet {
private String currentUser; // shared by all requests
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
currentUser = request.getParameter("user");
}
}
public class SafeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
String currentUser = request.getParameter("user"); // local to this request
}
}
Servlets can forward a request to another server-side resource or redirect the browser to a new URL. These actions look similar but behave differently.
| Action | Where It Happens | Browser URL Changes? | Use Case |
|---|---|---|---|
| Forward | Server | No | Send request to JSP or another Servlet. |
| Redirect | Client | Yes | Send user to another page after form submission. |
// Server-side forward
request.getRequestDispatcher("/WEB-INF/views/profile.jsp")
.forward(request, response);
// Client-side redirect
response.sendRedirect(request.getContextPath() + "/login");
Filters and listeners are related Servlet technologies. A filter can run before and after a request reaches a Servlet. A listener reacts to lifecycle events such as application startup, session creation, or request creation.
| Component | Purpose | Example |
|---|---|---|
| Servlet | Handles a request and creates a response. | ProductServlet |
| Filter | Intercepts requests/responses. | AuthenticationFilter, LoggingFilter |
| Listener | Responds to lifecycle events. | ServletContextListener |
In classic Java web MVC, the Servlet usually acts as the controller. It reads the request, calls service classes, stores results in request attributes, and forwards to a JSP view.
@WebServlet("/products")
public class ProductServlet extends HttpServlet {
private final ProductService productService = new ProductService();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<Product> products = productService.findAll();
request.setAttribute("products", products);
request.getRequestDispatcher("/WEB-INF/views/products.jsp")
.forward(request, response);
}
}
Servlets and JSP are often used together. A Servlet is better for Java control logic. JSP is better for rendering HTML views. In MVC, Servlets should not contain large amounts of HTML, and JSP should not contain large amounts of Java logic.
| Feature | Servlet | JSP |
|---|---|---|
| Primary role | Controller and request handling. | View rendering. |
| Written as | Java class. | HTML-like page with JSP tags. |
| Best for | Business flow, validation, routing. | Displaying dynamic HTML. |
| Bad use | Writing huge HTML strings. | Writing complex Java logic. |
Before Servlets, CGI was a common approach for dynamic server-side content. Servlets improved performance by using a managed Java runtime and threads instead of starting a new process for each request.
| Feature | Servlet | CGI |
|---|---|---|
| Execution model | Container-managed, usually multi-threaded. | Often one process per request. |
| Performance | Efficient for repeated requests. | Process startup can be expensive. |
| Session support | Built-in APIs. | Usually manual. |
| Portability | Runs on Java Servlet containers. | Depends on server and script environment. |
Servlet applications are commonly packaged as WAR files and deployed to a Servlet container. The standard project structure keeps Java code, web resources, libraries, and configuration in known locations.
servlet-demo/
src/main/java/com/example/
HelloServlet.java
src/main/webapp/
index.html
WEB-INF/
web.xml
views/
products.jsp
pom.xml
Servlets are a core part of Java web development. They connect HTTP requests to Java code, read input, call application logic, manage sessions, and generate responses. Even when using frameworks such as Spring MVC, understanding Servlets helps you understand what happens underneath every Java web request.
To master Servlets, focus on the container, lifecycle, request and response objects, URL mapping, HTTP methods, sessions, thread safety, filters, listeners, MVC flow, and deployment. These concepts form the base for the rest of Java web programming.
A Servlet instance is shared by many requests, often across multiple threads. If request-specific data is stored in an instance field, one user’s request can overwrite or leak into another user’s processing. Keep per-request data in local variables, request attributes, or scoped objects such as HttpSession when session state is truly intended.
Tomcat, as the Servlet container, maps URLs to Servlets, creates and initializes Servlet instances, manages request and response objects, runs filters, handles sessions, and calls lifecycle methods such as init, service, and destroy. Your Servlet code handles application behavior, but the container owns the web runtime around it.
GET is meant for safe reads and exposes form values in the URL. Use POST when submission changes server state or carries data that should stay out of bookmarks and routine cache keys.
Explore 500+ free tutorials across 20+ languages and frameworks.