← Назад к вопросам

Какие знаешь способы создания Servlet?

1.6 Junior🔥 141 комментариев
#REST API и микросервисы#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Способы создания Servlet

Servlet — это Java класс, расширяющий функциональность веб-серверов. Это основной компонент Java EE приложений, хотя сейчас часто заменяется фреймворками типа Spring MVC. Существует несколько способов создания Servlet'ов.

1. Расширение класса GenericServlet (Базовый способ)

Это абстрактный класс для создания сервлетов независимо от протокола.

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class MyGenericServlet extends GenericServlet {
    
    @Override
    public void service(ServletRequest request, ServletResponse response) 
            throws ServletException, IOException {
        
        // Установить тип контента
        response.setContentType("text/plain; charset=UTF-8");
        
        // Получить writer
        PrintWriter writer = response.getWriter();
        
        // Отправить ответ
        writer.println("Hello from GenericServlet");
        writer.flush();
        writer.close();
    }
}

Конфигурация в web.xml:

<servlet>
    <servlet-name>myGenericServlet</servlet-name>
    <servlet-class>com.example.MyGenericServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>myGenericServlet</servlet-name>
    <url-pattern>/generic</url-pattern>
</servlet-mapping>

Когда использовать: редко, в основном для протоколов не-HTTP.

2. Расширение класса HttpServlet (Стандартный способ)

Это специализированный класс для HTTP сервлетов. Используется в 99% случаев.

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class MyHttpServlet extends HttpServlet {
    
    // Обработка GET запросов
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter writer = response.getWriter();
        
        // Получить параметры
        String name = request.getParameter("name");
        if (name == null) name = "Guest";
        
        writer.println("<h1>Hello, " + name + "!</h1>");
        writer.close();
    }
    
    // Обработка POST запросов
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        
        response.setContentType("application/json");
        PrintWriter writer = response.getWriter();
        
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        
        writer.println("{\"name\": \"" + name + "\", \"age\": " + age + "}");
        writer.close();
    }
    
    // Обработка PUT запросов (Java 8+)
    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().println("Updated");
    }
    
    // Обработка DELETE запросов
    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        response.setStatus(HttpServletResponse.SC_NO_CONTENT);
    }
}

Конфигурация в web.xml:

<servlet>
    <servlet-name>myHttpServlet</servlet-name>
    <servlet-class>com.example.MyHttpServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>myHttpServlet</servlet-name>
    <url-pattern>/api/hello</url-pattern>
</servlet-mapping>

3. Использование аннотации @WebServlet (Servlet 3.0+)

Вместо web.xml конфигурируется аннотацией. Это современный и рекомендуемый способ.

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(
    name = "annotatedServlet",
    urlPatterns = {"/annotated", "/annotation"},  // Несколько URL'ов
    loadOnStartup = 1                             // Загрузить при старте
)
public class AnnotatedServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        response.setContentType("text/plain");
        response.getWriter().println("Hello from Annotated Servlet");
    }
}

Преимущества:

  • ✅ Нет необходимости в web.xml
  • ✅ Конфигурация рядом с кодом
  • ✅ Более современный подход

4. Реализация интерфейса Servlet (Редко)

Можно напрямую реализовать интерфейс Servlet.

import javax.servlet.*;
import java.io.IOException;

public class CustomServlet implements Servlet {
    
    private ServletConfig config;
    
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        System.out.println("Servlet initialized");
    }
    
    @Override
    public void service(ServletRequest request, ServletResponse response) 
            throws ServletException, IOException {
        response.getWriter().println("Custom servlet");
    }
    
    @Override
    public String getServletInfo() {
        return "Custom Servlet Implementation";
    }
    
    @Override
    public void destroy() {
        System.out.println("Servlet destroyed");
    }
    
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }
}

Когда использовать: редко, предпочитайте HttpServlet.

5. Сервлет с инициализацией параметров

Передача конфигурационных параметров сервлету.

@WebServlet(
    urlPatterns = "/config",
    initParams = {
        @WebInitParam(name = "database", value = "jdbc:mysql://localhost/mydb"),
        @WebInitParam(name = "username", value = "root"),
        @WebInitParam(name = "timeout", value = "30")
    }
)
public class ConfiguredServlet extends HttpServlet {
    
    private String database;
    private String username;
    private int timeout;
    
    @Override
    public void init() throws ServletException {
        ServletConfig config = getServletConfig();
        database = config.getInitParameter("database");
        username = config.getInitParameter("username");
        timeout = Integer.parseInt(config.getInitParameter("timeout"));
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        response.setContentType("text/plain");
        response.getWriter().println(
            "DB: " + database + ", User: " + username + ", Timeout: " + timeout
        );
    }
}

Альтернатива в web.xml:

<servlet>
    <servlet-name>configuredServlet</servlet-name>
    <servlet-class>com.example.ConfiguredServlet</servlet-class>
    <init-param>
        <param-name>database</param-name>
        <param-value>jdbc:mysql://localhost/mydb</param-value>
    </init-param>
</servlet>

6. Сервлет с фильтрацией запросов

Обработка конкретных типов контента или метода.

@WebServlet(
    urlPatterns = "/api/users/*",
    methods = {"GET", "POST", "PUT", "DELETE"}
)
public class UserApiServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        String pathInfo = request.getPathInfo();
        // /api/users/123 -> pathInfo = /123
        
        response.setContentType("application/json");
        response.getWriter().println("{\"id\": \"" + pathInfo + "\"}");
    }
}

7. Асинхронные Сервлеты (Servlet 3.0+)

Для долгоживущих операций, не блокирующих поток контейнера.

import javax.servlet.annotation.WebServlet;
import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
    urlPatterns = "/async",
    asyncSupported = true
)
public class AsyncServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        // Переключиться в асинхронный режим
        AsyncContext asyncContext = request.startAsync();
        asyncContext.setTimeout(10000); // 10 секунд timeout
        
        // Обработать в отдельном потоке
        asyncContext.start(() -> {
            try {
                // Долгая операция
                Thread.sleep(5000);
                
                response.setContentType("text/plain");
                response.getWriter().println("Async result");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                asyncContext.complete();
            }
        });
    }
}

Жизненный цикл Servlet

public class LifecycleServlet extends HttpServlet {
    
    // 1. Инициализация (вызывается ОДИН раз при загрузке)
    @Override
    public void init() throws ServletException {
        System.out.println("1. init() - Servlet инициализирован");
    }
    
    // 2. Обработка запроса (вызывается для КАЖДОГО запроса)
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws IOException {
        System.out.println("2. doGet() - Обработка запроса");
        response.getWriter().println("Hello");
    }
    
    // 3. Завершение (вызывается ОДИН раз при выключении сервера)
    @Override
    public void destroy() {
        System.out.println("3. destroy() - Servlet завершен");
    }
}

Сравнение способов

СпособСложностьИспользованиеКогда
GenericServletНизкаяРедкоNon-HTTP протоколы
HttpServletНизкаяСтандартноHTTP API
@WebServletНизкаяСовременноJava EE 3.0+
Implement ServletВысокаяРедкоСпециальные случаи
Async ServletСредняяСпециализированноДолгие операции

Лучшие практики

✅ Используйте HttpServlet вместо GenericServlet ✅ Предпочтите @WebServlet вместо web.xml ✅ Используйте асинхронные сервлеты для I/O операций ✅ Обрабатывайте исключения правильно ✅ Закрывайте ресурсы в finally ✅ Устанавливайте Content-Type ответа

❌ Не забывайте про init() и destroy() ❌ Не используйте instance variables для хранения состояния (thread-unsafe) ❌ Не блокируйте основной поток в обычных сервлетах

Примечание: В современных приложениях Servlet'ы редко используются напрямую — их заменили фреймворки типа Spring MVC, которые скрывают сложность Servlet API.