ZetCode

Java Servlet

last modified October 4, 2026

This tutorial shows how to create a simple Jakarta Servlet web application with Maven and run it on Jetty 12.

Java Servlet

Servlet is a Java class managed by a servlet container. For HTTP applications, a servlet handles requests and creates responses. Containers such as Tomcat and Jetty manage servlet lifecycle, routing, and communication with clients. Frameworks such as Spring MVC can build on the Servlet API.

Jakarta Servlet 5.0 and later use the jakarta.servlet and jakarta.servlet.http packages. Older Java EE examples may use the javax.servlet namespace; those imports are not interchangeable with the Jakarta packages used here.

Java Servlet example

In this example, the @WebServlet annotation maps a servlet to a URL. You can also declare servlet mappings in the web.xml deployment descriptor.

pom.xml
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │               HelloServlet.java
│   ├───resources
│   └───webapp
│           index.html
└───test
    └───java

This is the project structure.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
            http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>JavaServlet</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.3</version>
            </plugin>

            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-ee10-maven-plugin</artifactId>
                <version>12.0.38</version>
                <configuration>
                    <webApp>
                        <contextPath>/app</contextPath>
                    </webApp>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

This is the Maven POM file. The jakarta.servlet-api dependency provides the Servlet 6.0 API at compile time. Its provided scope keeps it out of the WAR because the servlet container supplies the API at runtime. Jetty 12's EE10 plugin provides a Servlet 6.0-compatible environment.

The maven-war-plugin packages the web application classes and resources into a Web Application Archive (WAR). The Jetty EE10 Maven plugin runs the application with mvn jetty:run during development.

<configuration>
    <webApp>
        <contextPath>/app</contextPath>
    </webApp>
</configuration>

In the Jetty Maven plugin, we set the context path to /app.

com/zetcode/HelloServlet.java
package com.zetcode;

import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet(name = "HelloServlet", urlPatterns = {"/hello"})
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException {

        response.setContentType("text/plain;charset=UTF-8");
        var out = response.getWriter();

        out.print("Hello there from Servlet");
    }
}

The HelloServlet returns a simple text message back to the client.

@WebServlet(name = "HelloServlet", urlPatterns = {"/hello"})

The @WebServlet annotation maps this class to the /hello URL pattern within the web application's context path.

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException {

The doGet method is called for GET requests. The method receives HttpServletRequest and HttpServletResponse objects.

response.setContentType("text/plain;charset=UTF-8");

The servlet sends output data in plain text and the encoding of the data is set to UTF-8.

var out = response.getWriter();

The getWriter method returns a writer for text responses. Because the response content type declares UTF-8, the writer encodes the text using that character set. The container manages the writer lifecycle.

out.print("Hello there from Servlet");

We write a text message with the print method.

webapp/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home page</title>
</head>
<body>

<p>
    This is home page. Call <a href="/app/hello">HelloServlet</a>
</p>

</body>
</html>

In the home page, we have a link that calls the servlet.

$ mvn jetty:run

The Jetty Maven plugin starts the server. Open http://localhost:8080/app/ and follow the link to call the servlet.

Source

Jakarta Servlet documentation

In this article, we created a Jakarta Servlet and ran the web application with Jetty.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Java tutorials.