0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Javalin - это не единственный фреймворк на Java, вместе со Spring Boot их десятки. Несмотря на это многообразие, все они базируются на механизме сервлетов (<em>servlets</em>). В этом уроке мы обсудим, что это такое и почему об этом нужно знать.</p>
1
<p>Javalin - это не единственный фреймворк на Java, вместе со Spring Boot их десятки. Несмотря на это многообразие, все они базируются на механизме сервлетов (<em>servlets</em>). В этом уроке мы обсудим, что это такое и почему об этом нужно знать.</p>
2
<h2>Клей между фреймворками и веб-серверами</h2>
2
<h2>Клей между фреймворками и веб-серверами</h2>
3
<p>Любой веб-фреймворк работает не сам по себе. Для запуска написанного на нем приложения нужен веб-сервер. Такой веб-сервер загружает приложение внутрь себя и запускает. Из этого следует два вывода:</p>
3
<p>Любой веб-фреймворк работает не сам по себе. Для запуска написанного на нем приложения нужен веб-сервер. Такой веб-сервер загружает приложение внутрь себя и запускает. Из этого следует два вывода:</p>
4
<ul><li>Такой веб-сервер должен быть написан на том же языке - например, в Java среди основных веб-серверов выделяют Tomcat и Jetty</li>
4
<ul><li>Такой веб-сервер должен быть написан на том же языке - например, в Java среди основных веб-серверов выделяют Tomcat и Jetty</li>
5
<li>Веб-сервер и фреймворк должны знать друг о друге, чтобы они могли работать совместно</li>
5
<li>Веб-сервер и фреймворк должны знать друг о друге, чтобы они могли работать совместно</li>
6
</ul><p>Теперь представьте, что у нас есть десятки фреймворков и десятки веб-серверов. Как им всем знать друг о друге? В худшем случае нам пришлось бы писать код для совместимости каждого с каждым. Это было бы пустой тратой ресурсов команд разработчиков, а создание нового фреймворка было бы очень затруднено.</p>
6
</ul><p>Теперь представьте, что у нас есть десятки фреймворков и десятки веб-серверов. Как им всем знать друг о друге? В худшем случае нам пришлось бы писать код для совместимости каждого с каждым. Это было бы пустой тратой ресурсов команд разработчиков, а создание нового фреймворка было бы очень затруднено.</p>
7
<p>К счастью, эта проблема решилась еще в конце девяностых, когда появилась спецификация сервлетов. С тех пор все веб-сервера ориентируются только на сервлеты, а фреймворки, используют сервлеты для своей работы "под капотом". Все, что мы писали на Javalin, внутри фреймворка превращается в сервлеты:</p>
7
<p>К счастью, эта проблема решилась еще в конце девяностых, когда появилась спецификация сервлетов. С тех пор все веб-сервера ориентируются только на сервлеты, а фреймворки, используют сервлеты для своей работы "под капотом". Все, что мы писали на Javalin, внутри фреймворка превращается в сервлеты:</p>
8
<p>Эта спецификация описывает способ написания универсального веб-приложения под Java, в котором код состоит из сервлетов.</p>
8
<p>Эта спецификация описывает способ написания универсального веб-приложения под Java, в котором код состоит из сервлетов.</p>
9
<p>Каждый сервлет - это класс, отвечающий за определенный маршрут. Во время работы веб-сервер принимает входящие запросы и передает их сервлетам, отвечающим за запрошенные адреса. Затем сервлеты возвращают ответы, которые отправляются клиентам.</p>
9
<p>Каждый сервлет - это класс, отвечающий за определенный маршрут. Во время работы веб-сервер принимает входящие запросы и передает их сервлетам, отвечающим за запрошенные адреса. Затем сервлеты возвращают ответы, которые отправляются клиентам.</p>
10
<p>Можно ли сделать вид, что для работы с фреймворками мы не обязаны ничего знать про сервлеты? С одной стороны, да, ведь сервлеты существуют только где-то внутри. На каком-то уровне их можно не замечать. С другой стороны, игнорировать сервлеты не стоит. Они встречаются везде: то в выводах в логах, то в настройках. Даже в Spring Boot настройки часто работают с механизмом сервлетов напрямую. Кроме того, о них могут спросить на собеседовании.</p>
10
<p>Можно ли сделать вид, что для работы с фреймворками мы не обязаны ничего знать про сервлеты? С одной стороны, да, ведь сервлеты существуют только где-то внутри. На каком-то уровне их можно не замечать. С другой стороны, игнорировать сервлеты не стоит. Они встречаются везде: то в выводах в логах, то в настройках. Даже в Spring Boot настройки часто работают с механизмом сервлетов напрямую. Кроме того, о них могут спросить на собеседовании.</p>
11
<h2>Первый сервлет</h2>
11
<h2>Первый сервлет</h2>
12
<p>Рассмотрим создание полноценного приложения с помощью сервлетов на примере репозитория<a>java-servlet-gradle</a>. Начнем с класса сервлета:</p>
12
<p>Рассмотрим создание полноценного приложения с помощью сервлетов на примере репозитория<a>java-servlet-gradle</a>. Начнем с класса сервлета:</p>
13
<p>Здесь мы видим переопределенный метод doGet(). Он вызывается на Get-запрос по адресу<em>/about</em>, указанному в аннотации. Внутри есть доступ к объектам запроса и ответа. В нашем примере данные запроса не используются, а вот в ответе отдается строчка текста. Перечислим моменты, на которые нужно обратить внимание:</p>
13
<p>Здесь мы видим переопределенный метод doGet(). Он вызывается на Get-запрос по адресу<em>/about</em>, указанному в аннотации. Внутри есть доступ к объектам запроса и ответа. В нашем примере данные запроса не используются, а вот в ответе отдается строчка текста. Перечислим моменты, на которые нужно обратить внимание:</p>
14
<ul><li>Jakarta (Jakarta EE) - это набор спецификаций и компонентов, предоставляющих решения для различных прикладных приложений. Туда входят и сервлеты и многое другое, что встречается в реальных проектах</li>
14
<ul><li>Jakarta (Jakarta EE) - это набор спецификаций и компонентов, предоставляющих решения для различных прикладных приложений. Туда входят и сервлеты и многое другое, что встречается в реальных проектах</li>
15
<li>Сервлет наследуется от класса HttpServlet, импортированного из Jakarta</li>
15
<li>Сервлет наследуется от класса HttpServlet, импортированного из Jakarta</li>
16
<li>Сервлет нужно пометить аннотацией @WebServlet с указанием имени и маршрута, за который этот сервлет отвечает</li>
16
<li>Сервлет нужно пометить аннотацией @WebServlet с указанием имени и маршрута, за который этот сервлет отвечает</li>
17
</ul><p>Так можно добавить любое количество сервлетов:</p>
17
</ul><p>Так можно добавить любое количество сервлетов:</p>
18
<p>Чтобы запустить веб-сервер с нашим приложением, понадобится кое-что еще установить и настроить. Ниже урезанная версия файла<a>build.gradle.kts</a>:</p>
18
<p>Чтобы запустить веб-сервер с нашим приложением, понадобится кое-что еще установить и настроить. Ниже урезанная версия файла<a>build.gradle.kts</a>:</p>
19
<p>После этого можно запустить приложение:</p>
19
<p>После этого можно запустить приложение:</p>
20
<p>После этого приложение станет доступно в браузере по адресу<em><a>http://localhost:8080</a></em>. Если открыть страницу<em><a>http://localhost:8080/about</a></em>, то мы увидим текст<em>Hello, Simple Servlet!</em>.</p>
20
<p>После этого приложение станет доступно в браузере по адресу<em><a>http://localhost:8080</a></em>. Если открыть страницу<em><a>http://localhost:8080/about</a></em>, то мы увидим текст<em>Hello, Simple Servlet!</em>.</p>
21
<h2>Шаблонизатор Java Server Pages (JSP)</h2>
21
<h2>Шаблонизатор Java Server Pages (JSP)</h2>
22
<p>Кроме сервлетов, Jakarta содержит в себе JSP. Это простой шаблонизатор, который можно использовать для генерации HTML-страниц на сервере. Для примера создадим другой сервлет и посмотрим, как использовать JSP:</p>
22
<p>Кроме сервлетов, Jakarta содержит в себе JSP. Это простой шаблонизатор, который можно использовать для генерации HTML-страниц на сервере. Для примера создадим другой сервлет и посмотрим, как использовать JSP:</p>
23
<p>Общая структура сервлета не поменялась, но добавилось несколько деталей:</p>
23
<p>Общая структура сервлета не поменялась, но добавилось несколько деталей:</p>
24
<ul><li>Данные, которые мы хотим передать в шаблон, нужно записывать в объект запроса через метод setAttribute()</li>
24
<ul><li>Данные, которые мы хотим передать в шаблон, нужно записывать в объект запроса через метод setAttribute()</li>
25
<li>Нужно явно указать, какой шаблон использовать</li>
25
<li>Нужно явно указать, какой шаблон использовать</li>
26
</ul><p>Для хранения шаблонов используется стандартная директория<em>src/main/webapp/WEB-INF</em>:</p>
26
</ul><p>Для хранения шаблонов используется стандартная директория<em>src/main/webapp/WEB-INF</em>:</p>
27
<p>В шаблоне можно отметить четыре важных элемента:</p>
27
<p>В шаблоне можно отметить четыре важных элемента:</p>
28
<ul><li>Первой строчкой идет c:forEach - директива для работы JSP-тегов (они начинаются с префикса c)</li>
28
<ul><li>Первой строчкой идет c:forEach - директива для работы JSP-тегов (они начинаются с префикса c)</li>
29
<li>Запрос и ответ доступны в шаблоне напрямую через переменные request и response</li>
29
<li>Запрос и ответ доступны в шаблоне напрямую через переменные request и response</li>
30
<li>Для вывода данных используется синтаксис <%= %>, внутри которого можно вызывать Java-код</li>
30
<li>Для вывода данных используется синтаксис <%= %>, внутри которого можно вызывать Java-код</li>
31
<li>Для управляющих конструкций используется синтаксис на нестандартных тегах, которые превращаются в обычный HTML после обработки</li>
31
<li>Для управляющих конструкций используется синтаксис на нестандартных тегах, которые превращаются в обычный HTML после обработки</li>
32
</ul><p>Для работы JSP нужно добавить несколько зависимостей:</p>
32
</ul><p>Для работы JSP нужно добавить несколько зависимостей:</p>
33
33