Home » Вопросы и ответы для собеседования по Servlet
Вопросы и ответы для собеседования по Servlet

Вопросы и ответы для собеседования по Servlet

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

## Что такое Servlet и как он работает?

Servlet — это Java-класс, который расширяет возможности сервера для обработки HTTP-запросов. По сути, это спецификация, которая определяет, как Java-приложения должны взаимодействовать с веб-серверами. Когда приходит запрос, контейнер сервлетов (типа Tomcat) создаёт экземпляр твоего сервлета и вызывает соответствующий метод.

Жизненный цикл сервлета включает:
• **Загрузка и инициализация** — вызов `init()`
• **Обработка запросов** — вызов `service()`, который делегирует в `doGet()`, `doPost()` и т.д.
• **Уничтожение** — вызов `destroy()`


public class HelloServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        // Инициализация ресурсов
        System.out.println("Servlet initialized");
    }
    
    @Override
    protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) 
                        throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("

Hello, World!

"); } @Override public void destroy() { // Очистка ресурсов System.out.println("Servlet destroyed"); } }

## Настройка сервлета: от конфигурации до деплоя

### Способ 1: Через web.xml (старая школа)


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         version="3.1">
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.example.HelloServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

### Способ 2: Через аннотации (современный подход)


@WebServlet(name = "HelloServlet", 
           urlPatterns = {"/hello"}, 
           loadOnStartup = 1)
public class HelloServlet extends HttpServlet {
    // твой код
}

### Быстрая настройка на VPS

Для тестирования и разработки тебе понадобится сервер. Можешь заказать VPS для небольших проектов или выделенный сервер для production-нагрузок.


# Установка Java и Tomcat на Ubuntu
sudo apt update
sudo apt install openjdk-11-jdk
sudo apt install tomcat9

# Создание WAR-файла
jar -cvf myapp.war *

# Деплой в Tomcat
sudo cp myapp.war /var/lib/tomcat9/webapps/
sudo systemctl restart tomcat9

## Разбор популярных вопросов с собеседований

### RequestDispatcher vs sendRedirect

Характеристика RequestDispatcher sendRedirect
Местоположение Серверная сторона Клиентская сторона
URL в браузере Остаётся прежним Меняется
Производительность Быстрее Медленнее (два запроса)
Область видимости Внутри приложения Любой URL

// RequestDispatcher (forward)
RequestDispatcher dispatcher = request.getRequestDispatcher("/result.jsp");
dispatcher.forward(request, response);

// sendRedirect
response.sendRedirect("/app/success.jsp");

### Работа с сессиями


// Получение сессии
HttpSession session = request.getSession();
session.setAttribute("username", "john_doe");

// Настройка таймаута
session.setMaxInactiveInterval(1800); // 30 минут

// Инвалидация сессии
session.invalidate();

### Фильтры — мощный инструмент

Фильтры позволяют перехватывать запросы и ответы до того, как они достигнут сервлета:


@WebFilter("/*")
public class LoggingFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, 
                        ServletResponse response, 
                        FilterChain chain) 
                        throws IOException, ServletException {
        
        long start = System.currentTimeMillis();
        
        // Выполнение запроса
        chain.doFilter(request, response);
        
        long duration = System.currentTimeMillis() - start;
        System.out.println("Request processed in: " + duration + "ms");
    }
}

## Практические кейсы и подводные камни

### ❌ Частые ошибки

**1. Thread Safety**
Сервлеты не thread-safe по умолчанию. Избегай instance variables:


// ПЛОХО
public class BadServlet extends HttpServlet {
    private int counter = 0; // Общий для всех потоков!
    
    protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) {
        counter++; // Race condition!
    }
}

// ХОРОШО
public class GoodServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) {
        int counter = 0; // Локальная переменная
        counter++;
    }
}

**2. Утечки памяти в сессиях**


// Плохая практика - большие объекты в сессии
session.setAttribute("heavyObject", new HeavyObject());

// Лучше использовать ID и кэш
session.setAttribute("objectId", objectId);
Object obj = cache.get(objectId);

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

**Конфигурация пула соединений в context.xml:**


<Context>
    <Resource name="jdbc/TestDB" 
              auth="Container" 
              type="javax.sql.DataSource"
              maxTotal="100" 
              maxIdle="30" 
              maxWaitMillis="10000"
              username="dbuser" 
              password="dbpass" 
              driverClassName="com.mysql.cj.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/testdb"/>
</Context>

## Альтернативы и современные подходы

### Spring Boot vs чистые Servlet

Аспект Чистые Servlet Spring Boot
Скорость разработки Медленно Быстро
Контроль Полный Ограниченный
Размер приложения Маленький Большой
Производительность Высокая Хорошая

### Микросервисы с Servlet


@WebServlet("/api/users/*")
public class UserApiServlet extends HttpServlet {
    
    @Override
    protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) 
                        throws ServletException, IOException {
        
        String pathInfo = request.getPathInfo();
        
        if (pathInfo.matches("/\\d+")) {
            // GET /api/users/123
            handleGetUser(request, response);
        } else {
            // GET /api/users
            handleGetUsers(request, response);
        }
    }
    
    private void handleGetUser(HttpServletRequest request, 
                              HttpServletResponse response) 
                              throws IOException {
        response.setContentType("application/json");
        response.getWriter().write("{\"id\": 123, \"name\": \"John\"}");
    }
}

## Нестандартные применения

### Servlet как WebSocket endpoint


@ServerEndpoint("/websocket")
public class WebSocketEndpoint {
    
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("Connection opened");
    }
    
    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            session.getBasicRemote().sendText("Echo: " + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

### Servlet для file upload


@WebServlet("/upload")
@MultipartConfig(
    maxFileSize = 1024 * 1024 * 5,      // 5MB
    maxRequestSize = 1024 * 1024 * 10   // 10MB
)
public class FileUploadServlet extends HttpServlet {
    
    protected void doPost(HttpServletRequest request, 
                         HttpServletResponse response) 
                         throws ServletException, IOException {
        
        Part filePart = request.getPart("file");
        String fileName = filePart.getSubmittedFileName();
        
        try (InputStream input = filePart.getInputStream()) {
            Files.copy(input, Paths.get("/uploads/" + fileName));
        }
    }
}

## Полезные ссылки и ресурсы

Официальная документация Servlet API
Документация Apache Tomcat
Jakarta Servlet API

## Интересные факты и статистика

Servlet API появился в 1997 году и до сих пор остаётся основой для большинства Java веб-приложений. Согласно опросам разработчиков, около 65% enterprise-приложений на Java используют Servlet API напрямую или через фреймворки.

Производительность чистых сервлетов может достигать 50,000+ запросов в секунду на обычном сервере, что делает их отличным выбором для высоконагруженных API.

## Автоматизация и скрипты

### Автоматический деплой с помощью Maven


<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <url>http://localhost:8080/manager/text</url>
        <server>TomcatServer</server>
        <path>/myapp</path>
    </configuration>
</plugin>

### Bash-скрипт для мониторинга


#!/bin/bash
# monitor_servlet.sh

APP_URL="http://localhost:8080/myapp/health"
LOG_FILE="/var/log/servlet-monitor.log"

while true; do
    RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" $APP_URL)
    
    if [ $RESPONSE -eq 200 ]; then
        echo "$(date): Application is healthy" >> $LOG_FILE
    else
        echo "$(date): Application is down! Response: $RESPONSE" >> $LOG_FILE
        # Restart Tomcat
        sudo systemctl restart tomcat9
    fi
    
    sleep 30
done

## Заключение и рекомендации

Servlet API — это не просто legacy-технология, а мощный инструмент, который стоит знать любому Java-разработчику. Даже если ты работаешь со Spring Boot, понимание принципов работы сервлетов поможет тебе лучше оптимизировать приложения и решать сложные задачи.

**Когда использовать чистые Servlet:**
• Микросервисы с минимальными зависимостями
• Высокопроизводительные API
• Embedded-приложения
• Когда нужен полный контроль над HTTP-обработкой

**Когда лучше выбрать фреймворк:**
• Rapid prototyping
• Большие enterprise-приложения
• Когда команда не очень опытная
• Проекты с жёсткими дедлайнами

Главное — не бояться “грязной” работы с низкоуровневыми API. Это знание всегда пригодится на собеседованиях и в реальных проектах, особенно когда что-то пойдёт не так в production.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked