Java Servlet API: полное руководство по созданию веб-приложений
Для кого эта статья:
- Java-разработчики, желающие углубить свои знания в создании веб-приложений
- Студенты и начинающие программисты, изучающие веб-разработку на Java
Профессионалы, работающие с фреймворками, желающие понять основы работы сервлетов
Java Servlet API — мощный инструмент для создания динамических веб-приложений, выдержавший проверку временем. Несмотря на появление множества современных фреймворков, сервлеты остаются фундаментальной технологией, понимание которой критически важно для Java-разработчика. В этом руководстве мы шаг за шагом разберём, как работать с Java Servlet API — от базовых концепций до написания функционального кода. Вы получите практические примеры, которые можно сразу применить в реальных проектах. 🚀
Хотите быстро освоить Java Servlet API и другие ключевые технологии веб-разработки? Курс Java-разработки от Skypro предлагает структурированную программу с акцентом на практику. Вы не просто изучите теорию сервлетов, но создадите полноценные веб-приложения под руководством опытных менторов. Курс включает реальные проекты для портфолио и поддержку в трудоустройстве после обучения.
Что такое Java Servlet API: основные концепции и применение
Java Servlet API представляет собой набор классов и интерфейсов, предназначенных для создания динамических веб-приложений на языке Java. По сути, сервлет — это Java-класс, который обрабатывает HTTP-запросы и генерирует соответствующие ответы.
Сервлеты выступают как связующее звено между клиентом (обычно веб-браузером) и базами данных или другими приложениями на стороне сервера. Основное преимущество сервлетов — их независимость от платформы и возможность использовать всю мощь Java.
Андрей Петров, тимлид отдела веб-разработки Когда я пришёл в компанию, наше старое веб-приложение было написано на чистых сервлетах без использования фреймворков. Сначала это казалось архаичным, но именно этот проект дал мне глубокое понимание работы веб-приложений на Java. Я увидел, как запрос проходит через фильтры, обрабатывается сервлетом, взаимодействует с бизнес-логикой и возвращается клиенту. Спустя год, когда мы начали миграцию на Spring MVC, я был единственным в команде, кто мог отлаживать проблемы на низком уровне, понимая, что происходит "под капотом" фреймворка. Знание сервлетов стало моим конкурентным преимуществом и ускорило мой карьерный рост.
Основные компоненты Java Servlet API включают:
- Servlet: интерфейс, определяющий основные методы, которые должен реализовать каждый сервлет
- ServletConfig: используется для передачи информации о конфигурации сервлету
- ServletContext: предоставляет информацию о среде, в которой работает сервлет
- ServletRequest и ServletResponse: обрабатывают запросы и ответы соответственно
- HttpServlet: расширение для обработки HTTP-запросов
Главные области применения Java Servlet API:
| Область применения | Описание | Преимущества |
|---|---|---|
| Веб-приложения | Создание динамических веб-сайтов с генерацией HTML-контента | Полный контроль над генерируемым HTML, интеграция с Java-экосистемой |
| RESTful API | Разработка API для взаимодействия с фронтендом или другими системами | Простая обработка HTTP-методов, гибкость в работе с данными |
| Корпоративные приложения | Построение серверной части для бизнес-приложений | Интеграция с корпоративными системами, высокая производительность |
| Шлюзы и прокси | Обработка и перенаправление запросов между системами | Возможность трансформации и валидации данных |
Несмотря на появление множества фреймворков высокого уровня (Spring, Jakarta EE), понимание работы сервлетов остается критически важным, поскольку эти фреймворки построены поверх Servlet API. Можно сказать, что изучение сервлетов — это как изучение анатомии для врача: без понимания базовых структур невозможно стать настоящим экспертом. 🧠

Настройка рабочей среды для разработки Java сервлетов
Для разработки приложений с использованием Java Servlet API требуется правильно настроенная среда. Рассмотрим последовательные шаги по созданию рабочего окружения, в котором вы сможете эффективно разрабатывать и тестировать сервлеты.
Прежде всего, вам потребуются следующие компоненты:
- Java Development Kit (JDK) 8 или выше
- Интегрированная среда разработки (IDE): IntelliJ IDEA, Eclipse или NetBeans
- Сервер приложений: Apache Tomcat, Jetty или WildFly
- Система сборки проекта: Maven или Gradle
Установка JDK — первый и самый важный шаг. После загрузки и установки JDK необходимо настроить переменные окружения JAVA_HOME и PATH.
Далее следует настроить сервер приложений. Apache Tomcat — наиболее популярный выбор для начинающих разработчиков. После установки Tomcat необходимо выполнить базовую настройку:
# Для Linux/Mac
export CATALINA_HOME=/path/to/tomcat
export PATH=$PATH:$CATALINA_HOME/bin
# Для Windows (PowerShell)
$env:CATALINA_HOME = "C:\path\to\tomcat"
$env:PATH += ";$env:CATALINA_HOME\bin"
Для создания проекта с сервлетами рекомендуется использовать Maven. Вот пример базовой структуры pom.xml:
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
Также требуется создать файл web.xml в директории WEB-INF для конфигурации веб-приложения:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>My Servlet Application</display-name>
</web-app>
Сравнение популярных IDE для разработки сервлетов:
| IDE | Преимущества | Недостатки | Встроенная поддержка сервлетов |
|---|---|---|---|
| IntelliJ IDEA | Мощный редактор, интеграция с серверами, умная автодополнение | Платная версия для всех возможностей, высокие требования к ресурсам | Отличная (шаблоны, интеграция с Tomcat, отладка) |
| Eclipse | Бесплатный, богатая экосистема плагинов, стабильность | Сложная настройка, местами устаревший интерфейс | Хорошая (требуется установка WTP) |
| NetBeans | Простая настройка, интуитивно понятный интерфейс | Более медленная работа, меньше плагинов | Средняя (базовые функции доступны) |
| VS Code | Лёгкий, быстрый, современный | Ограниченная встроенная поддержка Java и сервлетов | Слабая (требуются дополнительные расширения) |
После настройки среды разработки, рекомендуется создать простой проект-заготовку, который можно использовать как шаблон для будущих проектов. Включите в него базовый сервлет, страницу JSP и структуру директорий, соответствующую стандартам Java-веб-приложений. 📝
Также важно настроить отладку (debugging) в вашей IDE. Это позволит отслеживать выполнение кода сервлетов в реальном времени и значительно упростит разработку. В IntelliJ IDEA и Eclipse эта функциональность настраивается через конфигурации запуска сервера в режиме отладки.
Жизненный цикл сервлета: от создания до уничтожения
Понимание жизненного цикла сервлета — ключ к созданию эффективных и надёжных веб-приложений. Сервлет проходит через строго определённые этапы, каждый из которых имеет своё назначение и особенности.
Мария Соколова, Java-архитектор В начале моей карьеры я создала сервлет, который устанавливал соединение с базой данных в методе doGet(). Приложение работало, но было катастрофически медленным при большой нагрузке. Руководитель указал мне на фундаментальную ошибку: я не понимала жизненный цикл сервлета. После его объяснения я перенесла инициализацию соединения в метод init(), а закрытие — в destroy(). Производительность выросла в 5 раз. Вместо создания нового соединения для каждого запроса, сервлет использовал одно соединение на весь жизненный цикл. Это научило меня тому, что знание жизненного цикла сервлета — не теоретическая абстракция, а практический инструмент оптимизации.
Жизненный цикл сервлета состоит из трёх основных фаз:
- Инициализация — сервлет-контейнер загружает класс сервлета и создаёт его экземпляр
- Обслуживание — сервлет обрабатывает запросы от клиентов
- Уничтожение — сервлет завершает работу и освобождает ресурсы
Рассмотрим эти фазы подробнее:
Фаза 1: Инициализация
Когда сервлет-контейнер (например, Tomcat) запускается или получает первый запрос к сервлету, он выполняет следующие действия:
- Загружает класс сервлета через ClassLoader
- Создаёт единственный экземпляр сервлета
- Вызывает метод init(ServletConfig) для инициализации сервлета
Метод init() вызывается только один раз за всё время существования сервлета. Это идеальное место для:
- Чтения параметров инициализации из web.xml
- Установления соединений с базами данных
- Загрузки конфигурационных файлов
- Инициализации ресурсоёмких объектов
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
// Получение параметра инициализации
String databaseURL = config.getInitParameter("database-url");
// Инициализация соединения с БД
dbConnection = DatabaseManager.connect(databaseURL);
System.out.println("Servlet initialized");
}
Фаза 2: Обслуживание
После инициализации сервлет готов обрабатывать запросы. Для каждого запроса контейнер:
- Создаёт объекты HttpServletRequest и HttpServletResponse
- Вызывает метод service()
- Метод service() определяет тип HTTP-запроса и вызывает соответствующий метод (doGet(), doPost() и т.д.)
Важно понимать, что в отличие от init(), методы обслуживания вызываются для каждого запроса, часто параллельно в многопоточной среде. Это значит, что они должны быть потокобезопасными.
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
try (PrintWriter out = response.getWriter()) {
out.println("<html><body>");
out.println("<h1>Servlet Response</h1>");
out.println("</body></html>");
}
}
Фаза 3: Уничтожение
Сервлет уничтожается, когда:
- Контейнер сервлетов завершает работу
- Веб-приложение выгружается из контейнера
- Контейнер решает освободить ресурсы
При уничтожении контейнер вызывает метод destroy(). Это последний шанс для сервлета закрыть соединения, записать данные и выполнить другие операции очистки.
@Override
public void destroy() {
// Закрытие соединения с БД
if (dbConnection != null) {
try {
dbConnection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.println("Servlet destroyed");
super.destroy();
}
Вот сравнительная таблица методов жизненного цикла:
| Метод | Когда вызывается | Частота вызовов | Использование |
|---|---|---|---|
| init() | При создании экземпляра сервлета | Один раз | Инициализация ресурсов и загрузка конфигурации |
| service() | При каждом запросе к сервлету | Многократно | Распределение запросов по методам doXxx() |
| doGet() | При HTTP GET-запросе | Многократно | Обработка запросов на получение данных |
| doPost() | При HTTP POST-запросе | Многократно | Обработка запросов на изменение данных |
| destroy() | При уничтожении сервлета | Один раз | Освобождение ресурсов |
Понимание жизненного цикла сервлета критически важно для правильного проектирования веб-приложений. Игнорирование этих принципов может привести к утечкам памяти, проблемам производительности и даже потере данных. 🔄
Обработка HTTP-запросов в сервлетах: GET и POST методы
Обработка HTTP-запросов — основная задача сервлетов. Большинство веб-приложений активно используют методы GET и POST для различных операций. Каждый из этих методов имеет свои особенности и сценарии применения.
Обработка GET-запросов
GET-запросы преимущественно используются для получения данных. Параметры передаются в URL и видны пользователю. Рассмотрим стандартную структуру метода doGet():
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Установка типа содержимого и кодировки
response.setContentType("text/html;charset=UTF-8");
// Получение параметров запроса
String name = request.getParameter("name");
String id = request.getParameter("id");
// Формирование ответа
try (PrintWriter out = response.getWriter()) {
out.println("<html>");
out.println("<head><title>Get Response</title></head>");
out.println("<body>");
out.println("<h1>Hello, " + (name != null ? name : "Guest") + "!</h1>");
if (id != null) {
out.println("<p>Your ID: " + id + "</p>");
}
out.println("</body></html>");
}
}
Ключевые моменты при обработке GET-запросов:
- Параметры запроса извлекаются с помощью метода request.getParameter()
- Размер URL с параметрами ограничен (обычно 2048 символов)
- GET-запросы могут кэшироваться браузерами и серверами
- Не рекомендуется использовать GET для передачи конфиденциальных данных
Обработка POST-запросов
POST-запросы используются для отправки данных на сервер, особенно когда эти данные изменяют состояние приложения. Параметры передаются в теле запроса, что делает их невидимыми в URL.
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Установка типа содержимого и кодировки
response.setContentType("text/html;charset=UTF-8");
// Установка кодировки для правильного чтения параметров
request.setCharacterEncoding("UTF-8");
// Получение параметров формы
String username = request.getParameter("username");
String email = request.getParameter("email");
String password = request.getParameter("password");
// Проверка данных (очень простая)
boolean isValid = username != null && !username.trim().isEmpty() &&
email != null && email.contains("@") &&
password != null && password.length() >= 6;
// Формирование ответа
try (PrintWriter out = response.getWriter()) {
out.println("<html>");
out.println("<head><title>Registration Result</title></head>");
out.println("<body>");
if (isValid) {
// В реальном приложении здесь был бы код сохранения данных
out.println("<h1>Registration Successful!</h1>");
out.println("<p>Welcome, " + username + "!</p>");
} else {
out.println("<h1>Registration Failed</h1>");
out.println("<p>Please check your input and try again.</p>");
}
out.println("</body></html>");
}
}
Особенности обработки POST-запросов:
- Необходимо устанавливать кодировку с помощью request.setCharacterEncoding() перед чтением параметров
- POST-запросы не кэшируются и не могут быть добавлены в закладки
- Размер передаваемых данных практически не ограничен
- POST-запросы безопаснее для передачи конфиденциальной информации (но всё равно требуют HTTPS)
- После обработки POST-запроса рекомендуется выполнить перенаправление (PRG-паттерн) для предотвращения повторной отправки формы
Перенаправление и переадресация
Существует два основных способа перехода к другому ресурсу после обработки запроса:
// Перенаправление (клиент получает код 302 и новый URL)
response.sendRedirect("success.jsp");
// Переадресация (происходит на сервере, клиент "не видит" изменения URL)
request.getRequestDispatcher("success.jsp").forward(request, response);
Обработка загрузки файлов
Для обработки загружаемых файлов требуется специальный подход:
- В HTML-форме должен быть указан атрибут enctype="multipart/form-data"
- Для обработки необходима библиотека, например Apache Commons FileUpload
Обработка ошибок
Профессиональный подход к обработке запросов включает правильную обработку ошибок:
try {
// Код, который может вызвать исключение
processBusinessLogic(request);
} catch (SQLException e) {
// Логирование ошибки
logger.error("Database error", e);
// Установка кода ошибки
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
// Отправка сообщения об ошибке
response.getWriter().write("Database error occurred: " + e.getMessage());
}
Поддержка правильных HTTP-статусов помогает клиентам корректно обрабатывать ответы:
- 200 OK — запрос успешно обработан
- 400 Bad Request — некорректный запрос
- 401 Unauthorized — требуется аутентификация
- 404 Not Found — ресурс не найден
- 500 Internal Server Error — ошибка на сервере
Эффективная обработка HTTP-запросов в сервлетах требует понимания не только синтаксиса Java, но и принципов работы протокола HTTP. Владение этими навыками позволяет создавать надёжные и безопасные веб-приложения. 🔒
Практические примеры кода сервлетов для веб-приложений
Теперь применим полученные знания на практике. Ниже представлены готовые к использованию примеры сервлетов для различных сценариев веб-разработки. Эти примеры можно скопировать, адаптировать под свои нужды и использовать как отправную точку для ваших проектов.
1. Простой сервлет "Hello World"
Начнём с базового примера — сервлета, который выводит приветствие:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Hello Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Hello, World from Servlet!</h1>");
out.println("</body>");
out.println("</html>");
}
}
}
Обратите внимание на аннотацию @WebServlet, которая заменяет конфигурацию в web.xml. Это современный способ маппинга URL к сервлетам.
2. Сервлет для обработки формы регистрации
Этот сервлет демонстрирует работу с данными формы и реализацию базовой валидации:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
@WebServlet("/register")
public class RegistrationServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// Имитация базы данных пользователей
private final Map<String, String> users = new HashMap<>();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Отобразить форму регистрации
request.getRequestDispatcher("/WEB-INF/views/register.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Получение и валидация данных
String username = request.getParameter("username");
String email = request.getParameter("email");
String password = request.getParameter("password");
String confirmPassword = request.getParameter("confirmPassword");
// Проверка данных
Map<String, String> errors = new HashMap<>();
if (username == null || username.trim().isEmpty()) {
errors.put("username", "Username is required");
} else if (users.containsKey(username)) {
errors.put("username", "Username already exists");
}
if (email == null || !email.contains("@")) {
errors.put("email", "Valid email is required");
}
if (password == null || password.length() < 6) {
errors.put("password", "Password must be at least 6 characters");
} else if (!password.equals(confirmPassword)) {
errors.put("confirmPassword", "Passwords do not match");
}
if (!errors.isEmpty()) {
// Если есть ошибки – возвращаемся к форме
request.setAttribute("errors", errors);
request.setAttribute("username", username);
request.setAttribute("email", email);
request.getRequestDispatcher("/WEB-INF/views/register.jsp").forward(request, response);
return;
}
// Сохранение пользователя (в реальном приложении – в БД)
users.put(username, password);
// Создание сессии для пользователя
HttpSession session = request.getSession();
session.setAttribute("username", username);
// Перенаправление на домашнюю страницу
response.sendRedirect(request.getContextPath() + "/home");
}
}
3. Сервлет для работы с сессиями и cookies
Демонстрирует управление сессией и cookies для отслеживания пользователя:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet("/session-demo")
public class SessionDemoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// Получаем сессию (создаём новую, если не существует)
HttpSession session = request.getSession();
// Получаем счётчик посещений или устанавливаем в 0
Integer visitCount = (Integer) session.getAttribute("visitCount");
if (visitCount == null) {
visitCount = 0;
}
// Увеличиваем и сохраняем счётчик
visitCount++;
session.setAttribute("visitCount", visitCount);
// Устанавливаем cookie с именем пользователя
String username = request.getParameter("username");
if (username != null && !username.isEmpty()) {
Cookie userCookie = new Cookie("username", username);
userCookie.setMaxAge(60 * 60 * 24 * 30); // 30 дней
response.addCookie(userCookie);
}
// Получаем имя пользователя из cookie
String savedUsername = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("username".equals(cookie.getName())) {
savedUsername = cookie.getValue();
break;
}
}
}
// Выводим информацию
try (PrintWriter out = response.getWriter()) {
out.println("<!DOCTYPE html>");
out.println("<html><head><title>Session Demo</title></head><body>");
out.println("<h1>Session and Cookie Demo</h1>");
out.println("<h2>Session Info:</h2>");
out.println("<p>Session ID: " + session.getId() + "</p>");
out.println("<p>Visit Count: " + visitCount + "</p>");
out.println("<h2>Cookie Info:</h2>");
if (savedUsername != null) {
out.println("<p>Welcome back, " + savedUsername + "!</p>");
} else {
out.println("<p>No username cookie found.</p>");
}
out.println("<h2>Set Your Name:</h2>");
out.println("<form method='get'>");
out.println("Username: <input type='text' name='username'>");
out.println("<input type='submit' value='Save'>");
out.println("</form>");
out.println("</body></html>");
}
}
}
4. Сервлет для работы с базой данных (JDBC)
Демонстрирует взаимодействие с базой данных:
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/users")
public class UserListServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// JDBC URL, username и password следует настроить для вашей БД
private static final String JDBC_URL = "jdbc:mysql://localhost:3306/userdb";
private static final String JDBC_USER = "root";
private static final String JDBC_PASSWORD = "password";
private Connection getConnection() throws SQLException {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
} catch (ClassNotFoundException e) {
throw new SQLException("JDBC Driver not found", e);
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter();
Connection conn = getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
out.println("<!DOCTYPE html>");
out.println("<html><head><title>User List</title></head><body>");
out.println("<h1>User List</h1>");
out.println("<table border='1'>");
out.println("<tr><th>ID</th><th>Username</th><th>Email</th></tr>");
while (rs.next()) {
out.println("<tr>");
out.println("<td>" + rs.getInt("id") + "</td>");
out.println("<td>" + rs.getString("username") + "</td>");
out.println("<td>" + rs.getString("email") + "</td>");
out.println("</tr>");
}
out.println("</table>");
out.println("</body></html>");
} catch (SQLException e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().println("Database error: " + e.getMessage());
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String email = request.getParameter("email");
if (username == null || username.trim().isEmpty() || email == null || email.trim().isEmpty()) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Username and email are required");
return;
}
try (Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO users (username, email) VALUES (?, ?)")) {
pstmt.setString(1, username);
pstmt.setString(2, email);
int rowsAffected = pstmt.executeUpdate();
if (rowsAffected > 0) {
response.sendRedirect(request.getContextPath() + "/users");
} else {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Insert failed");
}
} catch (SQLException e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().println("Database error: " + e.getMessage());
e.printStackTrace();
}
}
}
5. Сервлет для загрузки и скачивания файлов
Демонстрирует работу с файлами:
import java.io.*;
import java.nio.file.Paths;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/file")
@MultipartConfig
public class FileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// Директория для хранения загруженных файлов
private static final String UPLOAD_DIRECTORY = "uploads";
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Отображаем форму для загрузки файла или скачиваем файл, если указан параметр download
String fileName = request.getParameter("download");
if (fileName != null && !fileName.isEmpty()) {
// Скачивание файла
File file = new File(getUploadPath() + File.separator + fileName);
if (!file.exists()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "File not found");
return;
}
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setContentLength((int) file.length());
try (FileInputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
} else {
// Отображаем форму для загрузки
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<!DOCTYPE html>");
out.println("<html><head><title>File Upload/Download</title></head><body>");
out.println("<h1>File Upload</h1>");
out.println("<form method='post' enctype='multipart/form-data'>");
out.println("Select file: <input type='file' name='file'><br><br>");
out.println("<input type='submit' value='Upload'>");
out.println("</form>");
// Список загруженных файлов
out.println("<h2>Uploaded Files:</h2>");
File uploadDir = new File(getUploadPath());
if (uploadDir.exists() && uploadDir.isDirectory()) {
File[] files = uploadDir.listFiles();
if (files != null && files.length > 0) {
out.println("<ul>");
for (File f : files) {
if (f.isFile()) {
out.println("<li><a href='?download=" + f.getName() + "'>" +
f.getName() + "</a> (" + f.length() + " bytes)</li>");
}
}
out.println("</ul>");
} else {
out.println("<p>No files uploaded yet.</p>");
}
}
out.println("</body></html>");
}
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Создаём директорию, если она не существует
File uploadDir = new File(getUploadPath());
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// Получаем файл из запроса
Part filePart = request.getPart("file");
if (filePart == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No file uploaded");
return;
}
// Получаем имя файла
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
// Сохраняем файл
filePart.write(getUploadPath() + File.separator + fileName);
// Перенаправляем обратно на страницу
response.sendRedirect(request.getContextPath() + "/file");
}
private String getUploadPath() {
return getServletContext().getRealPath("") + File.separator + UPLOAD_DIRECTORY;
}
}
Эти примеры демонстрируют основные сценарии использования сервлетов. Обратите внимание, что в реальных приложениях необходимо реализовывать дополнительные меры безопасности, такие как защита от SQL-инъекций, XSS-атак, CSRF и других уязвимостей. Также рекомендуется использовать пулы соединений для работы с базой данных и разделять код на слои (MVC-архитектура). 🛡️
Овладение Java Servlet API открывает широкие возможности для разработки серверных приложений. Несмотря на появление множества фреймворков высокого уровня, понимание сервлетов остаётся фундаментальным навыком для каждого Java-разработчика. Начните с простых примеров, постепенно внедряйте изученные концепции в свои проекты и помните: знание жизненного цикла сервлетов и правильная обработка HTTP-запросов — залог создания надёжных и производительных веб-приложений.