Servlets Explained: The Foundation of Java Web Apps

    Atul Kabra4 min readUpdated

    A servlet is a Java class that runs inside a web server (a "servlet container" such as Apache Tomcat or Jetty) and handles incoming HTTP requests by producing HTTP responses. In plain terms: a browser asks for a page, the servlet container hands that request to your servlet, your code runs, and you send back HTML, JSON, or any other content. Servlets are the bedrock layer that almost every Java web technology — JSP, Spring MVC, Spring Boot — is built on top of.

    If you understand servlets, the rest of the Java backend world stops looking like magic.

    How a servlet handles a request

    When a request arrives, the container looks at the URL and decides which servlet should handle it. It then calls one of the servlet's methods based on the HTTP method:

    • doGet() for GET requests (reading a page)
    • doPost() for POST requests (submitting a form)
    • doPut(), doDelete() and others for the remaining HTTP methods

    You override the method you need. The container passes in two objects: an HttpServletRequest (everything the client sent) and an HttpServletResponse (where you write your reply).

    The servlet lifecycle

    A servlet has a predictable life managed entirely by the container:

    1. Loading and instantiation — the container creates a single instance of your servlet class.
    2. init() — called once, right after creation. Use it for one-time setup (database pools, config).
    3. service() — called for every request; it routes to doGet, doPost, etc. You usually do not override service() directly.
    4. destroy() — called once before the servlet is removed, so you can release resources.

    A key point that surprises beginners: the container creates one instance and serves many concurrent requests through it on different threads. So your servlet must be thread-safe — avoid mutable instance fields that change per request.

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses

    Your first servlet

    Modern servlets live in the jakarta.servlet package (the older javax.servlet namespace was renamed when Java EE moved to the Eclipse Foundation as Jakarta EE). Here is a complete, working example:

    // Import the Jakarta Servlet API (NOT the old javax.* packages)
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    // @WebServlet maps this servlet to the URL "/greet" — no XML config needed
    @WebServlet("/greet")
    public class GreetServlet extends HttpServlet {
    
        // Called automatically for GET requests to /greet
        @Override
        protected void doGet(HttpServletRequest request,
                             HttpServletResponse response) throws IOException {
    
            // Read a query parameter, e.g. /greet?name=Asha
            String name = request.getParameter("name");
            if (name == null || name.isBlank()) {
                name = "learner"; // safe default
            }
    
            // Tell the browser we are sending HTML in UTF-8
            response.setContentType("text/html;charset=UTF-8");
    
            // Write the response body
            try (PrintWriter out = response.getWriter()) {
                out.println("<h1>Hello, " + name + "!</h1>");
                out.println("<p>This page was generated by a Java servlet.</p>");
            }
        }
    }
    

    Deploy this to Tomcat, visit http://localhost:8080/yourapp/greet?name=Asha, and the servlet builds the page on the fly.

    Common mistakes

    • Using javax.servlet instead of jakarta.servlet. Any current container (Tomcat 10+, Jetty 11+) expects the jakarta namespace. Mixing them causes "ClassNotFound" or unmapped-servlet errors.
    • Storing per-request data in instance fields. Because one instance serves many threads, a shared field like private String currentUser; will leak data between users. Keep request-scoped data in local variables.
    • Forgetting to set the content type. Without response.setContentType(...), browsers may guess wrong and render your HTML as plain text.
    • Doing heavy setup in doGet. Database connections and config belong in init(), which runs once, not on every request.
    • Not closing the writer/stream. Use try-with-resources, as shown above, so the response is flushed and resources are freed.

    FAQ

    Do I still need to learn servlets if I use Spring Boot? Spring Boot hides most servlet code, but it runs on a servlet container underneath. Knowing servlets helps you debug filters, sessions, and request handling when the abstraction leaks.

    What is a servlet container? It is the runtime that manages servlet lifecycle and threading — Tomcat and Jetty are the most common. Spring Boot embeds one for you.

    Is web.xml required? No. The @WebServlet annotation replaces most XML configuration in modern apps.

    Keep learning

    Servlets are step one. Next, see how JSP builds views on top of servlets, how MVC architecture organises the whole app, and explore the full Advanced Java hub.


    Ready to build real Java backends from the ground up? Join the waitlist for the Advanced Java course at Infoplanet, Jalgaon, and learn servlets, Spring Boot, and REST APIs with hands-on guidance.

    Want to learn this properly?

    Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.

    Browse courses
    Atul Kabra

    Founder, Infoplanet

    Atul Kabra founded Infoplanet in 2001 and has spent over two decades teaching programming — C, C++, Java, databases and more — to students across Maharashtra.

    Related guides