Java Servlet
The foundational Java server-side technology for handling HTTP requests, underpinning Tomcat, Spring MVC, and most of the Java web ecosystem since 1997.
Created by Pavni Diwanji and James Duncan Davidson (Sun Microsystems)
Java Servlet (now formally Jakarta Servlet) is the foundational server-side technology of the Java web platform. A servlet is a Java class that runs inside a servlet container (also called a web container) and responds to requests – most commonly HTTP requests – by generating responses such as HTML pages, JSON payloads, or redirects. Rather than being a standalone programming language, the Servlet API is a specification and set of Java interfaces (HttpServlet, ServletRequest, ServletResponse, Filter, and others) that define how Java code participates in the request/response cycle of a web server. First released in 1997 as a portable, object-oriented alternative to CGI scripts, the Servlet API became the bedrock on which nearly all subsequent Java web technology – JavaServer Pages, JavaServer Faces, Apache Struts, and Spring MVC – was built.
History & Origins
From CGI to Servlets
In the mid-1990s, dynamic web content was generated primarily through the Common Gateway Interface (CGI), which spawned a new operating-system process for every incoming request. This model was simple but resource-intensive and difficult to scale. Sun Microsystems saw an opportunity to apply Java’s “write once, run anywhere” portability and its threading model to server-side web programming: instead of forking a process per request, a servlet could be loaded once and serve many concurrent requests as lightweight threads within a single JVM.
The concept of server-side Java components is often traced to James Gosling in Java’s earliest days, and Sun introduced the idea publicly around the inaugural JavaOne conference in May 1996. The first formal Servlet specification (Servlet 1.0) was authored by Pavni Diwanji at Sun Microsystems.
First Release (1997)
The Java Servlet API became a usable product in 1997. Sun shipped the Java Servlet Development Kit (JSDK) carrying the Servlet 1.0 API, and the Java Web Server (developed under the codename Jeeves) was released on June 5, 1997, as the first commercial server to run servlets. A full reference implementation rewrite was led by James Duncan Davidson, who would later create both Apache Tomcat and Apache Ant.
Note: sources differ slightly on the exact timing of the very first Servlet 1.0 deliverables – some place the specification’s finalization in late 1996 alongside early Sun web-server builds, while the broadly shipped JSDK and Java Web Server arrived in mid-1997. The 1997 date is used here as the practical first appearance of the technology as a generally available product.
Donation to Apache and Standardization
In 1999, Sun donated its servlet and JSP reference implementation to the Apache Software Foundation, where it became Apache Tomcat – still the canonical servlet container today. That same year, Servlet 2.2 was folded into the Java 2 Platform, Enterprise Edition (J2EE 1.2), cementing servlets as a core part of enterprise Java and introducing the WAR file as the standard deployment unit. From this point forward the Servlet API evolved under the Java Community Process as a Java Specification Request (JSR), tracking each release of the J2EE / Java EE platform.
Design Philosophy
A Specification, Not an Implementation
The defining characteristic of the Servlet model is the separation of specification from implementation. The Servlet API defines a contract – a set of interfaces and lifecycle rules – while multiple independent vendors provide compliant servlet containers (Tomcat, Jetty, Undertow, WildFly, GlassFish, WebLogic, WebSphere). Application code written against the API is portable across any compliant container.
The Container-Managed Lifecycle
Servlets do not control their own creation or destruction. The container manages a well-defined lifecycle:
- Loading and instantiation – the container loads the servlet class and creates an instance.
- Initialization – the container calls
init()once, allowing the servlet to perform setup. - Request handling – for each request the container calls
service(), which dispatches todoGet(),doPost(),doPut(), and so on. A single servlet instance handles many concurrent requests on separate threads. - Destruction – the container calls
destroy()before removing the servlet.
Because one instance serves many threads, servlet code is expected to be thread-safe and to avoid mutable instance state.
Request/Response Abstraction
Servlets work through two key abstractions: a request object encapsulating the incoming data (headers, parameters, body, session) and a response object for producing output (status codes, headers, the output stream or writer). This clean abstraction insulates application code from the low-level details of socket handling and HTTP parsing.
Key Features
The HttpServlet Base Class
Most servlets extend HttpServlet and override the HTTP-method handlers. A minimal example:
| |
The @WebServlet annotation (introduced in Servlet 3.0) maps the servlet to a URL pattern without requiring an entry in the web.xml deployment descriptor.
Filters and Listeners
Filters (added in Servlet 2.3) intercept requests and responses to apply crosscutting behavior – authentication, compression, logging, character-encoding normalization – without modifying the servlets themselves. Listeners respond to lifecycle events such as application startup, session creation, and attribute changes.
Sessions and State
The Servlet API provides HttpSession for tracking state across the stateless HTTP protocol, typically backed by a cookie (JSESSIONID) or URL rewriting. The container manages session creation, timeout, and clustering.
Deployment Descriptor and WAR Files
Web applications are packaged as WAR (Web Application Archive) files containing servlets, static resources, libraries, and an optional web.xml deployment descriptor. Since Servlet 3.0, most configuration can be expressed through annotations, making web.xml optional.
Asynchronous and Non-Blocking I/O
Servlet 3.0 added asynchronous processing, letting a servlet release its request thread while long-running work completes elsewhere – important for scalability under high concurrency. Servlet 3.1 extended this with non-blocking I/O, allowing data to be read and written via event-driven callbacks rather than blocking calls.
Evolution
The Servlet API has advanced in lockstep with the broader enterprise Java platform:
| Version | Year | Platform | Notable additions |
|---|---|---|---|
| 1.0 | 1997 | JSDK | Initial release; portable alternative to CGI |
| 2.2 | 1999 | J2EE 1.2 | Becomes part of J2EE; WAR files |
| 2.3 | 2001 | J2EE 1.3 | Filters and lifecycle listeners |
| 2.4 | 2003 | J2EE 1.4 | XML Schema for web.xml |
| 2.5 | 2005 | Java EE 5 | Annotation support; requires Java SE 5 |
| 3.0 | 2009 | Java EE 6 | Async processing, web fragments, annotation config |
| 3.1 | 2013 | Java EE 7 | Non-blocking I/O, protocol upgrade |
| 4.0 | 2017 | Java EE 8 | HTTP/2 and server push |
| 5.0 | 2020 | Jakarta EE 9 | javax.servlet → jakarta.servlet namespace |
| 6.0 | 2022 | Jakarta EE 10 | Removal of deprecated features |
| 6.1 | 2024 | Jakarta EE 11 | HTTP/2 push deprecated; SecurityManager references removed |
The Jakarta Namespace Migration
The most consequential change in the Servlet API’s recent history was not a new feature but a rename. After Oracle donated Java EE to the Eclipse Foundation at the end of 2017, Oracle’s retention of the Java trademark meant the javax.* package namespace could no longer evolve. With Jakarta Servlet 5.0 (Jakarta EE 9, 2020), the entire API moved from javax.servlet to jakarta.servlet. This was a hard, breaking change requiring code, frameworks, and tooling across the ecosystem to update import statements – a migration that took the community several years to absorb and that still shapes library compatibility today (for example, Apache Tomcat 10 and later use the jakarta.servlet namespace, while Tomcat 9 and earlier remain on javax.servlet).
Current Relevance
Despite being over a quarter-century old, the Servlet API remains the substrate of the Java web world. Developers rarely write raw servlets today, but the technology is omnipresent beneath higher-level frameworks:
- Spring MVC dispatches all requests through a single front-controller servlet (
DispatcherServlet), and Spring Boot embeds a servlet container so applications run as self-contained executables. - Jakarta Server Pages (JSP) are compiled into servlets behind the scenes.
- Jakarta Faces (JSF) runs atop the
FacesServlet. - Embeddable containers like Eclipse Jetty put servlet handling inside countless products and microservices.
The specification continues to evolve under the Eclipse Foundation’s Jakarta EE umbrella, with Jakarta Servlet 6.1 finalized in March 2024 as part of Jakarta EE 11. Modern reactive and fully non-blocking stacks (such as Spring WebFlux built on Netty) offer alternatives to the servlet model for some workloads, but the servlet-based stack remains the default and most broadly supported approach to building web applications in Java.
Why It Matters
Java Servlets demonstrated that server-side web programming could be portable, object-oriented, and efficient. By replacing the process-per-request CGI model with long-lived, multithreaded components running inside a managed container, servlets established a performance and architecture pattern that influenced web platforms well beyond Java.
More importantly, the servlet container abstraction – a vendor-neutral specification with many competing implementations – proved enormously durable. It created a portable target that an entire generation of web frameworks could build on, allowing Struts, JSF, and Spring to flourish without each having to solve HTTP handling, threading, session management, and deployment from scratch. Almost every Java web application written in the last twenty-five years, whether the developer realizes it or not, ultimately handles its HTTP traffic through a servlet. That quiet ubiquity is the clearest measure of the Servlet API’s lasting impact on programming practice.
Timeline
Notable Uses & Legacy
Apache Tomcat
The most widely deployed servlet container and the official reference implementation of the Jakarta Servlet and Jakarta Server Pages specifications. Tomcat executes servlets, manages their lifecycle, and serves countless production Java web applications.
Spring Framework / Spring Boot
Spring MVC is built on top of the Servlet API: its central DispatcherServlet routes HTTP requests to controllers. Spring Boot embeds a servlet container (Tomcat, Jetty, or Undertow) so applications run as standalone JARs.
Eclipse Jetty
A lightweight, embeddable servlet container widely used inside other products and frameworks when a small, programmatically configured HTTP server is needed rather than a full application server.
Jakarta Faces (JSF)
The component-based web UI framework runs as a servlet (the FacesServlet) within a servlet container, relying on the Servlet API for request handling, session management, and the application lifecycle.
Jenkins
The popular automation server is packaged as a Java web application that runs inside an embedded servlet container, exposing its entire UI and REST API through servlet-based request handling.
Language Influence
Influenced By
Influenced
Running Today
Run examples using the official Docker image:
docker pull tomcat:10.1Example usage:
docker run --rm -it -p 8080:8080 tomcat:10.1