Перейти к содержимому
шпаргалка.
Esc
навигацияоткрыть⌘Jпредпросмотр
На этой странице

Сервлеты

Все темы Java Developer

Что такое «сервлет»?

Сервлет представляет серверный компонент для обработки запросов; жизненным циклом управляет контейнер. Технология развивается в Jakarta Servlet. Примеры ниже используют прежнее пространство имён javax.servlet из Java EE; начиная с Jakarta Servlet 5 используется jakarta.servlet.

Основные особенности сервлетов:

  1. Обработка HTTP-запросов: Сервлеты могут обрабатывать различные HTTP-запросы (GET, POST и т.д.).

  2. Жизненный цикл: Жизненный цикл сервлета управляется контейнером сервлетов (например, Apache Tomcat) и включает этапы инициализации (init), обработки запросов (service) и уничтожения (destroy).

  3. Динамическое создание контента: Сервлеты могут генерировать динамический контент, такой как HTML, JSON, XML и другие форматы.

Пример простого сервлета:

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

public class HelloWorldServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        response.getWriter().println("<h1>Hello, World!</h1>");
    }
}

В этом примере сервлет HelloWorldServlet обрабатывает HTTP GET запросы и возвращает простой HTML-ответ “Hello, World!”.


В чем заключаются преимущества технологии сервлетов над CGI (Common Gateway Interface)?

Преимущества технологии сервлетов над CGI (Common Gateway Interface):

  1. Производительность:

    • Сервлеты: Загружаются в память один раз и остаются в ней, обслуживая множество запросов. Это снижает накладные расходы на создание процессов для каждого запроса.

    • CGI: Для каждого запроса создается новый процесс, что увеличивает накладные расходы и снижает производительность.

  2. Многопоточность:

    • Сервлеты: Используют многопоточность, что позволяет обрабатывать множество запросов параллельно в одном процессе.

    • CGI: Каждый запрос запускается в отдельном процессе, что менее эффективно.

  3. Управление памятью:

    • Сервлеты: Управляются JVM (Java Virtual Machine), что позволяет использовать механизмы управления памятью, такие как сборка мусора.

    • CGI: Управление памятью и ресурсами зависит от операционной системы, что может приводить к более высокому потреблению ресурсов.

  4. Безопасность:

    • Сервлеты: Могут использовать мощные встроенные механизмы безопасности Java, включая контроль доступа и обработку исключений.

    • CGI: Менее гибкие и безопасные, требуют дополнительной настройки для обеспечения безопасности.

  5. Переносимость:

    • Сервлеты: Написаны на Java, что обеспечивает переносимость между различными платформами и серверами приложений.

    • CGI: Скрипты зависят от языка программирования и платформы, на которой они выполняются, что может ограничивать переносимость.

  6. Легкость разработки и обслуживания:

    • Сервлеты: Предоставляют богатый API и поддержку различных средств разработки, что упрощает создание и сопровождение веб-приложений.

    • CGI: Написание и обслуживание CGI-скриптов может быть более сложным из-за ограниченных возможностей и инструментов.


Какова структура веб-проекта?

Структура веб-проекта обычно включает следующие основные компоненты:

  1. Исходный код:

    • Java-классы: Контроллеры, сервисы, DAO (Data Access Objects), модели.

    • Сервлеты: Классы, обрабатывающие запросы.

  2. Ресурсы:

    • Статические ресурсы: HTML, CSS, JavaScript, изображения и другие статические файлы.

    • Шаблоны: Файлы шаблонов для динамического формирования HTML (например, JSP, Thymeleaf).

  3. Конфигурация:

    • web.xml: Файл конфигурации веб-приложения (указывается маппинг сервлетов, фильтры и другие параметры).

    • application.properties или application.yml: Файлы конфигурации параметров приложения (например, для Spring Boot).

    • context.xml или server.xml: Файлы конфигурации сервера (например, для Apache Tomcat).

  4. Библиотеки:

    • JAR-файлы: Зависимости и библиотеки, используемые в проекте.
  5. Тесты:

    • Unit-тесты: Тесты для проверки отдельных компонентов.

    • Integration-тесты: Тесты для проверки взаимодействия между компонентами.

  6. Средства сборки:

    • build.gradle или pom.xml: Скрипты сборки и управления зависимостями (например, для Gradle или Maven).

Пример структуры веб-проекта на Java (Maven):

my-webapp/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── controller/
│   │   │           ├── service/
│   │   │           ├── dao/
│   │   │           └── model/
│   │   ├── resources/
│   │   │   ├── application.properties
│   │   │   └── messages.properties
│   │   ├── webapp/
│   │   │   ├── WEB-INF/
│   │   │   │   ├── web.xml
│   │   │   │   └── views/
│   │   │   │       └── index.jsp
│   │   │   ├── css/
│   │   │   ├── js/
│   │   │   └── images/
│   ├── test/
│   │   └── java/
│   │       └── com/
│   │           └── example/
│   │               ├── controller/
│   │               ├── service/
│   │               ├── dao/
│   │               └── model/
└── pom.xml

Что такое «контейнер сервлетов»?

Контейнер сервлетов — это компонент веб-сервера или сервера приложений, который управляет жизненным циклом сервлетов, обрабатывает их запросы и предоставляет необходимые ресурсы и услуги.

Основные функции контейнера сервлетов:

  1. Управление жизненным циклом: Инициализация, обработка запросов и уничтожение сервлетов.

  2. Обработка запросов и ответов: Прием HTTP-запросов от клиентов, передача их сервлетам и отправка HTTP-ответов обратно клиентам.

  3. Безопасность: Управление безопасностью приложений, аутентификация и авторизация пользователей.

  4. Управление ресурсами: Обеспечение доступа к ресурсам, таким как базы данных, файлы и внешние службы.

  5. Конфигурация и деплоймент: Обработка конфигурационных файлов (например, web.xml), управление настройками и развертывание веб-приложений.

Примеры контейнеров сервлетов:

  • Apache Tomcat
  • Jetty
  • GlassFish
  • WildFly

Контейнер сервлетов играет ключевую роль в функционировании веб-приложений, обеспечивая их стабильность, безопасность и масштабируемость.


Что такое «дескриптор развертывания»?

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

Основной дескриптор развертывания для Java веб-приложений называется web.xml и находится в директории WEB-INF веб-приложения.

Пример содержимого web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                             http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.example.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>LoggingFilter</filter-name>
        <filter-class>com.example.LoggingFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>LoggingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <context-param>
        <param-name>maxUsers</param-name>
        <param-value>100</param-value>
    </context-param>

    <listener>
        <listener-class>com.example.AppListener</listener-class>
    </listener>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Protected Area</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.html</form-login-page>
            <form-error-page>/error.html</form-error-page>
        </form-login-config>
    </login-config>

    <security-role>
        <role-name>admin</role-name>
    </security-role>

</web-app>

В этом примере дескриптор развертывания web.xml описывает:

  • Сервлет HelloServlet и его маппинг на URL /hello.

  • Фильтр LoggingFilter, который применяется ко всем URL (/*).

  • Параметр контекста maxUsers с значением 100.

  • Листенер AppListener.

  • Список файлов приветствия (index.html и index.jsp).

  • Конфигурацию безопасности для защищенной области /admin/*, которая требует роль admin.

  • Конфигурацию формы логина и безопасности.


В каком случае требуется переопределять метод service()?

Переопределять метод service() требуется в тех случаях, когда необходимо кастомизировать обработку всех типов HTTP-запросов (GET, POST, PUT, DELETE и т.д.) в одном методе. Метод service() отвечает за распределение входящих запросов к соответствующим методам (doGet(), doPost(), doPut(), doDelete() и т.д.) сервлета.

Основные случаи, когда может потребоваться переопределение метода service():

  1. Универсальная обработка логики: Когда нужно выполнить общую логику для всех типов запросов до или после их обработки.

  2. Альтернативное распределение запросов: Когда требуется нестандартная маршрутизация или дополнительная логика распределения запросов.

  3. Обработка специальных HTTP-методов: HttpServlet уже поддерживает OPTIONS и TRACE через doOptions и doTrace. Переопределение service может понадобиться для нестандартной диспетчеризации; для общей предобработки часто подходит Filter.

Пример переопределения метода service():

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

public class CustomServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Общая логика для всех типов запросов
        System.out.println("Request received");

        // Вызываем родительский метод для стандартной обработки
        super.service(req, resp);

        // Логика после обработки запроса
        System.out.println("Response sent");
    }
}

Почему обычно переопределяют init() без аргументов в GenericServlet?

Контейнер вызывает Servlet.init(ServletConfig). Реализация GenericServlet сохраняет конфигурацию и затем вызывает удобный hook init() без аргументов. Обычно переопределяют этот hook. Если переопределён init(ServletConfig), вызов super.init(config) сохраняет базовую инициализацию.

Основные причины переопределения метода init() без аргументов:

  1. Инициализация ресурсов: Метод init() используется для выполнения инициализации ресурсов, необходимых для работы сервлета (например, подключение к базе данных, настройка параметров).

  2. Упрощение кода: Переопределение метода без аргументов позволяет сосредоточиться на логике инициализации, не отвлекаясь на детали инициализации, переданные через ServletConfig.

  3. Совместимость: init() без аргументов сохраняет стандартную работу GenericServlet.init(ServletConfig), включая сохранение ServletConfig.

Пример переопределения метода init():

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        // Инициализация ресурсов
        System.out.println("Servlet is being initialized");
    }
}

Что вы знаете о сервлетных фильтрах?

Сервлетные фильтры — это компоненты веб-приложения, которые позволяют перехватывать и изменять запросы и ответы в сервлетах. Они предоставляют механизм для выполнения предобработки и постобработки запросов и ответов.

Основные особенности сервлетных фильтров:

  1. Предобработка и постобработка: Фильтры могут выполнять действия перед тем, как запрос достигнет сервлета, и после того, как сервлет обработает запрос и сформирует ответ.

  2. Цепочка фильтров: Несколько фильтров могут быть связаны в цепочку, где каждый фильтр может передать управление следующему фильтру или конечному сервлету.

  3. Переиспользование кода: Фильтры позволяют переиспользовать код для общих задач, таких как аутентификация, логирование, сжатие данных и т.д.

Пример фильтра, который логирует все запросы:

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

public class LoggingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        // Инициализация фильтра
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        System.out.println("Request URI: " + httpRequest.getRequestURI());

        // Передача управления следующему фильтру или сервлету
        chain.doFilter(request, response);
    }

    public void destroy() {
        // Очистка ресурсов
    }
}

В этом примере фильтр LoggingFilter перехватывает каждый запрос, логирует его URI и затем передает управление следующему элементу цепочки (другому фильтру или сервлету) с помощью метода chain.doFilter().

Фильтры конфигурируются в дескрипторе развертывания web.xml или с помощью аннотаций:

<filter>
    <filter-name>LoggingFilter</filter-name>
    <filter-class>com.example.LoggingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LoggingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Или с помощью аннотаций:

import javax.servlet.annotation.WebFilter;

@WebFilter("/*")
public class LoggingFilter implements Filter {
    // методы фильтра
}

Как реализовать запуск сервлета одновременно с запуском приложения?

Для реализации запуска сервлета одновременно с запуском приложения, можно использовать параметр load-on-startup в дескрипторе развертывания web.xml. Этот параметр указывает контейнеру сервлетов инициализировать и загружать сервлет при старте приложения, а не при первом запросе к нему.

Пример конфигурации web.xml:

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.example.MyServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/myservlet</url-pattern>
</servlet-mapping>

В этом примере MyServlet будет загружен и инициализирован при старте приложения. Значение 1 в элементе load-on-startup задает порядок загрузки сервлетов. Сервлеты с меньшими значениями загружаются раньше. Положительное значение (например, 1) указывает на необходимость загрузки при старте, тогда как отрицательное значение или его отсутствие означает, что сервлет будет загружен при первом запросе к нему.

Если используются аннотации, можно добавить аннотацию @WebServlet и указать параметр loadOnStartup:

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;

@WebServlet(urlPatterns = "/myservlet", loadOnStartup = 1)
public class MyServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        super.init();
        // Код инициализации сервлета
        System.out.println("MyServlet is initialized");
    }
}

В этом примере сервлет MyServlet также будет загружен при старте приложения благодаря параметру loadOnStartup = 1 в аннотации @WebServlet.

Эта страница была полезной?