Java Сервлеты¶
Java-сервлеты. Особенности реализации, ключевые методы, преимущества и недостатки относительно CGI и FastCGI.
серверные компоненты для создания динамических страниц, генерируемых на сервере
работают внутри контейнера сервлетов (например, Apache Tomcat, Jetty, GlassFish)
обрабатывают HTTP-запросы
Клиент отправляет HTTP-запрос
Веб-сервер перенаправляет запрос в контейнер сервлетов, который управляет жизненным циклом сервлетов
Контейнер вызывает соответствующий сервлет, передавая данные запроса
Сервлет обрабатывает запрос и формирует ответ (HTML, JSON...)
Сервлет отправляет ответ обратно в контейнер -> передает веб-серверу -> клиенту
Чтобы создать сервлет, нужно:
Создать класс, который наследуется от HttpServlet
Переопределить методы, такие как doGet() и doPost(), для обработки соответствующих HTTP-запросов
Зарегистрировать сервлет в файле конфигурации (например, web.xml) или с использованием аннотаций, таких как @WebServlet
Методы Java-сервлетов
init() — вызывается контейнером сервлетов при инициализации сервлета. Этот метод выполняется один раз при первом запросе к сервлету.
doGet(HttpServletRequest request, HttpServletResponse response) — обрабатывает GET-запросы.
doPost(HttpServletRequest request, HttpServletResponse response) — обрабатывает POST-запросы.
destroy() — вызывается контейнером при завершении работы сервлета. Используется для освобождения ресурсов.
CGI
Каждый запрос порождает новый процесс
FastCGI
постоянные процессы, которые обрабатывают несколько запросов
может использоваться с любым языком программирования
Java-сервлеты
сервлеты работают в многопоточном режиме
один экземпляр сервлета для обработки нескольких запросов
встроенная поддержка HTTP-сессий
легко переносятся на разные серверы и платформы
Требуется наличие контейнера, что добавляет дополнительный уровень настройки и управления
требует значительных ресурсов памяти, особенно для сложных приложений
Контейнеры сервлетов. Жизненный цикл сервлета.
серверная платформа для развертывания и выполнения Java-сервлетов
управляет жизненным циклом сервлетов
обрабатывает запросы и обеспечивает взаимодействие между сервлетами и веб-сервером
Примеры контейнеров сервлетов:
Apache Tomcat
Jetty
GlassFish
WildFly
Контейнеры сервлетов обеспечивают:
создание, инициализацию, обработку запросов и уничтожение сервлетов
принимает HTTP-запросы от клиентов, обрабатывает их, вызывает соответствующий сервлет и отправляет обратно HTTP-ответ
поддерживают многопоточность, позволяя одному сервлету обслуживать несколько клиентских запросов одновременно
обеспечивают безопасность, управляя доступом к ресурсам и обрабатывая аутентификацию и авторизацию пользователей
поддержка сессий
Как работают контейнеры сервлетов?
Запуск сервера: Контейнер сервлетов запускается и слушает HTTP-запросы на определенном порту.
Загрузка сервлета: Когда поступает запрос к сервлету, контейнер либо загружает класс сервлета (если он еще не загружен), либо использует уже существующий экземпляр.
Создание экземпляра сервлета: Контейнер создает экземпляр сервлета (если он не существует) и вызывает метод init().
Обработка запроса: Для каждого HTTP-запроса контейнер создает новый поток, который вызывает методы doGet() или doPost() сервлета.
Формирование ответа: Сервлет формирует HTTP-ответ, который контейнер отправляет клиенту.
Завершение работы: Когда сервер отключается или необходимо освободить ресурсы, контейнер вызывает метод destroy() для уничтожения экземпляра сервлета.
Диспетчеризация запросов в сервлетах. Фильтры сервлетов.
это механизм перенаправления запросов от одного сервлета к другому или на другую страницу
Внутреннее перенаправление (Forward):
перенаправление запроса на другой сервлет, JSP внутри одного сервера без участия клиента
браузер не видит этого перенаправления
RequestDispatcher dispatcher = request.getRequestDispatcher("anotherServlet");
dispatcher.forward(request, response);
Внешнее перенаправление (Redirect):
код 302 - перенаправление
клиент видит изменение URL в адресной строке.
response.sendRedirect("http://www.example.com");
Фильтры сервлетов — объекты, позволяют перехватывать и модифицировать запросы и ответы до и после их обработки сервлетами
позволяют добавлять кросс-канальные функции, такие как аутентификация, логирование, сжатие, фильтрация контента и кэширование.
Как работают фильтры?
Клиент отправляет HTTP-запрос
Фильтр перехватывает запрос, модифицирует его или проверяет
Запрос передается в сервлет
Сервлет обрабатывает запрос и формирует ответ
Фильтр перехватывает ответ перед отправкой клиенту, модифицирует его при необходимости
Ответ отправляется клиенту
Создание фильтра
нужно реализовать интерфейс Filter и переопределить три метода:
init(FilterConfig filterConfig) — инициализация фильтра. Вызывается один раз при создании фильтра.
doFilter(ServletRequest request, ServletResponse response, FilterChain chain) — основная логика фильтрации. Выполняется при каждом запросе.
destroy() — уничтожение фильтра, выполняется перед его удалением.
@WebFilter("/myServlet")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Инициализация фильтра
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// Логирование запроса перед отправкой в сервлет
System.out.println("Запрос перед обработкой сервлетом");
// Передача запроса следующему фильтру или сервлету
chain.doFilter(request, response);
// Логирование после обработки запроса
System.out.println("Ответ после обработки сервлетом");
}
@Override
public void destroy() {
// Очистка ресурсов при уничтожении фильтра
}
}
Примеры использования фильтров
Аутентификация: Проверка, авторизован ли пользователь, и при отсутствии прав доступа — перенаправление на страницу логина.
Логирование: Логирование информации о каждом запросе (IP-адрес, время, метод запроса).
Кэширование: Изменение заголовков HTTP-ответа для контроля кэширования контента.
Сжатие: Сжатие HTTP-ответа для экономии трафика.
HTTP-сессии - назначение, взаимодействие сервлетов с сессией, способы передачи идентификатора сессии.
позволяет сохранять состояние пользователя между несколькими запросами
тк HTTP - stateless, сессии позволяют ассоциировать разные запросы с одним и тем же пользователем
HttpSession session = request.getSession();
session.setAttribute("username", "JohnDoe");
String username = (String) session.getAttribute("username");
Способы передачи идентификатора сессии
Для ассоциации каждого запроса с конкретной сессией используется идентификатор сессии (Session ID)
Этот идентификатор позволяет серверу различать запросы разных пользователей и поддерживать состояние
Контекст сервлета - назначение, способы взаимодействия сервлетов с контекстом.
предоставляет сервлетам интерфейс для взаимодействия с веб-приложением
для хранения информации, доступной всем сервлетам в приложении.
существует в течение всего времени работы веб-приложения
Назначение ServletContext:
Хранение общих данных: Позволяет хранить данные, которые доступны всем сервлетам в рамках одного веб-приложения.
Доступ к параметрам конфигурации: Содержит параметры конфигурации, определенные в файле web.xml.
Логирование: Предоставляет методы для записи логов и ошибок, которые происходят в приложении.
Доступ к ресурсам: Позволяет сервлетам взаимодействовать с файлами и ресурсами, находящимися в пределах веб-приложения (например, HTML, JSP, текстовые файлы).
Общение между сервлетами: Используется для обмена данными и взаимодействия между разными сервлетами.
Способы взаимодействия сервлетов с контекстом
ServletContext context = getServletContext();
context.setAttribute("sharedData", "This is shared data");
String sharedData = (String) context.getAttribute("sharedData");
JSP (Java Server Pages)¶
JavaServer Pages. Особенности, преимущества и недостатки по сравнению с сервлетами, область применения.
для создания динамически генерируемых веб-страниц
отделение логики приложения (Java-код) от его представления (HTML-контент)
JSP автоматически компилируются в сервлеты при первом запуске, что избавляет от необходимости вручную создавать сервлеты
Жизненный цикл JSP.
Жизненный цикл JSP во многом похож на жизненный цикл сервлета, так как JSP в конечном итоге компилируется в сервлет
Основные этапы жизненного цикла JSP выглядят следующим образом:
контейнер преобразует JSP в Java файл
контейнер компилирует Java в .class файл (сервлет)
после успешной компиляции класс сервлета загружается в контейнер
затем вызывается метод jspInit(), который инициализирует JSP
после инициализации JSP переходит в состояние готовности к обработке HTTP-запросов
для каждого запроса вызывается метод jspService(), который обрабатывает запрос и генерирует ответ
когда контейнер JSP обнаруживает, что JSP больше не нужен или сервер останавливается, он вызывает метод jspDestroy()
Структура JSP-страницы. Комментарии, директивы, объявления, скриптлеты и выражения.
Комментарии
<%-- Это комментарий JSP, не попадает в HTML-выход --%>
Директивы
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<%@ include file="header.jsp" %>
Объявления
<%! private int counter = 0; %>
Скриптлеты - произвольный Java-код
<% counter++; // Изменение переменной %>
Выражения
<p>Сообщение: <%= message %></p>
Правила записи Java-кода внутри JSP. Стандартные переменные, доступные в скриптлетах и выражениях.
request
response
session
out.println
Bean-компоненты и их использование в JSP.
JavaBeans — это классические Java-классы, которые следуют определенным соглашениям и
используются для инкапсуляции данных и бизнес-логики в Java-приложениях, включая JSP.
JavaBeans могут содержать свойства, методы доступа (геттеры и сеттеры) и могут быть
легко использованы в JSP для отображения данных и управления состоянием
Основные характеристики JavaBeans
Конструктор по умолчанию: JavaBean должен иметь публичный конструктор без параметров.
Приватные свойства: Все свойства (поля) должны быть объявлены как приватные, чтобы обеспечить инкапсуляцию.
Геттеры и сеттеры: Для доступа к свойствам должны быть определены публичные методы-геттеры и сеттеры.
Сериализация: JavaBeans могут реализовывать интерфейс Serializable, что позволяет сохранять состояние объекта.
public class User implements Serializable {
private String name;
private int age;
public User() {}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
Использование JavaBeans в JSP
JavaBeans могут быть использованы в JSP для передачи данных и отображения их в веб-страниц
отделяет бизнес-логику от представления
JavaBeans — это простые Java-классы, которые используются для управления данными в веб-приложениях. Вот основные причины, зачем они нужны
Создание JavaBean: Как показано выше, создайте класс JavaBean с необходимыми свойствами и методами.
Импортирование JavaBean в JSP: Используйте директиву <%@ page import="..." %> для импорта вашего JavaBean.
Создание и настройка JavaBean: Создайте экземпляр JavaBean и настройте его свойства с помощью скриптлетов или выражений.
Использование тегов JSP: Для доступа к свойствам JavaBean используйте специальные теги, такие как <jsp:useBean>, <jsp:setProperty> и <jsp:getProperty>.
<%@ page import="com.example.User" %>
<jsp:useBean id="user" class="com.example.User" scope="session" />
<jsp:setProperty name="user" property="name" value="Алексей" />
<jsp:setProperty name="user" property="age" value="30" />
<p>Имя: <jsp:getProperty name="user" property="name" /></p>
<p>Возраст: <jsp:getProperty name="user" property="age" /></p>
Стандартные теги JSP. Использование Expression Language (EL) в JSP.
JSP (JavaServer Pages) предоставляет стандартные теги и возможности использования Expression Language (EL)
для упрощения работы с данными и динамическим контентом на веб-страницах
Стандартные теги JSP
<jsp:useBean>:
<jsp:useBean id="user" class="com.example.User" scope="session" />
<jsp:setProperty>:
<jsp:setProperty name="user" property="name" value="Алексей" />
<jsp:getProperty>:
<p>Имя: <jsp:getProperty name="user" property="name" /></p>
<jsp:include>:
<jsp:include page="header.jsp" />
<jsp:forward>:
<jsp:forward page="welcome.jsp" />
Использование Expression Language (EL) в JSP
Expression Language (EL) — это упрощенный способ доступа к данным, хранящимся в объектах, таких
как JavaBeans, коллекции и атрибуты сессии
Пример JSP с использованием стандартных тегов и EL
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:useBean id="user" class="com.example.User" scope="session" />
<jsp:setProperty name="user" property="name" value="Алексей" />
<jsp:setProperty name="user" property="age" value="30" />
<html>
<head>
<title>Пример JSP с EL и стандартными тегами</title>
</head>
<body>
<h2>Информация о пользователе:</h2>
<p>Имя: ${user.name}</p>
<p>Возраст: ${user.age}</p>
<c:if test="${user.age >= 18}">
<p>Вы совершеннолетний.</p>
</c:if>
<h3>Список покупок:</h3>
<c:forEach var="item" items="${shoppingList}">
<p>${item.name}</p>
</c:forEach>
</body>
</html>
Параметры конфигурации JSP в дескрипторе развёртывания веб-приложения.
конфигурация web.xml
Основные параметры конфигурации JSP в web.xml
<context-param>
<param-name>appName</param-name>
<param-value>My Web Application</param-value>
</context-param>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.example.MyServlet</servlet-class>
<init-param>
<param-name>maxUsers</param-name>
<param-value>100</param-value>
</init-param>
</servlet>
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.example.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Параметры JSP в jsp-config
Внутри элемента <jsp-config> могут быть указаны специфические настройки для всех JSP-страниц приложения:
<jsp-property-group>: Группирует параметры для нескольких JSP-страниц, чтобы избежать дублирования. Он может содержать следующие параметры:
<url-pattern>: Определяет шаблон URL для сопоставления с данной группой параметров.
<el-ignored>: Указывает, нужно ли игнорировать выражения EL.
<scripting-invalid>: Определяет, допустимо ли использование скриптлетов в JSP.
<is-xml>: Указывает, является ли JSP-страница XML-совместимой.
<trim-directive-whitespaces>: Определяет, следует ли удалять пробелы в директивах JSP.