JavaRush /Java блог /Архив info.javarush /Без пафоса. Поговорим о Java EE, сервлетах и их контейнер...
eGarmin
41 уровень

Без пафоса. Поговорим о Java EE, сервлетах и их контейнерах

Статья из группы Архив info.javarush
В этом топике я бы хотел откровенно поговорить о моем понимании сервлетов, что есть контейнеры сервлетов, что представляют собой большинство, если не все, веб-фронт-энд-фреймворки, а также коснуться темы, как соотносятся между собой контейнеры сервлетов и сервера приложений, и контейнеры сервлетов и веб-сервера. Без пафоса. Поговорим о Java EE, сервлетах и их контейнерах - 1Перед тем как начать разговор хочу отметить, что я действительно рассчитываю, что получится дискуссия, т.к. здесь мне не хочется приводить ни кусочка кода, а хочется коснуться лишь сути, которую всегда можно изложить на словах. Попытаюсь изложить все те моменты, которые были мне самому не понятны, когда я только начинал. Когда я задавал вопросы на разных форумах на тему, чем отличается контейнер сервлетов Tomcat от любого сервера приложений, скажем WebSphere или Geronimo, то отвечать решались только козлы, которые не могут сказать ничего, кроме как «смотри википедию» или «это сложно сказать, сервер приложений – это для корпоративных приложений сложная инфраструктура, которая…» бла-бла-бла. Терпеть таких не могу и полагаю, что большинство из вас тоже. Будем исправлять историческую несправедливость. Поехали…

Сервлеты

Чтобы кто там ни говорил, сервлет – это веб-страница, написанная на Java. Некоторые скажут, что я не прав и сервлет – это веб-приложение и что есть разница в этих понятиях, но это не так. Сейчас уже разницы нет, и сайты, написанные на PHP, тоже можно смело называть веб-приложениями. Теперь это полностью закономерно, т.к. php поддерживает ООП в полной мере, а такие CMS как Joomla активно этим пользуются. Что представляет собой сервлет на уровне кода? Это класс, в котором есть ряд методов, которые спят и видят, чтобы кто-то обратился к ним через GET или POST запросы HTTP. Т.е. набрали мы в браузере некоторый запрос GET, соответствующий метод класса сервлета его принимает и далее формирует ответ на него в виде html-страницы. В классическом понимании сервлета, как он был задуман еще Sun, эта страница так и отправлялась клиенту строчка за строчкой, начиная со строки <!DOCTYPE htm>> и заканчивая строкой </ html>. Таким образом, в Java есть базовый сервлет класс по имени Servlet. Кроме того, есть куча других классов, которые наследуются от этого базового класса и, тем самым, расширяют его функциональность. Вот, что такое сервлет – более ничего. Просто Java аналог PHP кода, который также выполняется на сервере, а клиенту посылается только ответ на запрос веб-браузера в виде веб-страницы. Всё.

Веб-фронт-энд-фреймворки

Подзаголовок сложноват и обычно все же пишут просто фронт-энд-фреймворк или даже веб-морда, но я решил здесь подчеркнуть, что когда речь идет о фронт-энд-фреймворках, то говорят о GUI для работы с Java через веб-браузер. Т.е. здесь опять идет речь о веб-сайтах на Java, т.е. о сервлетах. Что же представляет собой почти любой фронт-энд фреймфорк, к примеру, Apache Struts. Это просто набор классов, расширяющих базовый класс Servlet. Более ничего. Т.е. это просто другой способ создать тот же самый обычный сервлет. Просто разработчики этого фреймфорка (или иначе говоря, разработчики этой технологии) посчитали, что их дополнение базового Servlet-класса кое-какими методами будет более удобно для программиста, чем тот скудный функционал, что есть у классического сервлета от Sun/Oracle.

JSP-страницы

Практически сразу же в голову разработчиков концепции Java-сервлетов пришла еще одна идея. Раз уж мы пишем сервлет, задача которого – это отправка клиенту html-страницы, то может правильнее сразу написать эту html-страницу, а уж если понадобится какая-то логика на Java, то просто вставлять ее непосредственно в html. Если понятнее не стало, то может поможет фраза: jsp-страница – это аналог php-страницы. Сложно? Тогда еще поясню. Что мы делаем при написании страницы на php? У нас идет статический html, а когда нужно вставить всякую логику на php типа циклов и условий, то мы вставляет ее в тело тега <?php … ?>. С jsp все тоже самое, только логика пишется на чистой Java, код которой вставляется в тело тега <% … %>. Еще раз вернемся к понятию сервлета. По сути jsp-страница – это и есть сервлет, но записанный несколько иначе. В обычном сервлете мы пишем метод, который выполняет некоторую логику и по ее результатам формирует для клиента html-страницу. Просто через какое-то время разработчики сервлетов задумались, а что, если в методе не будет практически никакой логики, а будет идти почти одно лишь формирование html-страницы, то не проще ли будет писать сразу html-страницу, в которую делать минимальные вставки Java кода. Ну и последнее по поводу jsp-страниц. При первом обращении к такой странице она компилируется в сервлет и после этого выполняется. Последующие запросы к этой jsp-странице будут идти быстрее, т.к. она уже будет скомпилирована и ее нужно будет только выполнить.

Контейнер сервлетов

Вот написали мы класс сервлета или jsp-страницу. Что дальше? Как их запихнуть в веб-сервер, скажем apache, чтобы тот смог их отправить пользовательскому веб-браузеру? Веб-сервер может посылает только html, а если на нашей странице есть, скажем, php-код, то веб-сервер сначала пропускает страницу через интерпретатор, переводящий php в html, и только потом результат отправляется клиенту. С сервлетами происходит примерно тоже самое – перед отправкой их нужно выполнить, чтобы сформировалась html страница, а контейнер сервлетов как раз та самая штука, которая отвечает за выполнение сервлетов и кода jsp-страниц. Т.е. контейнер сервлетов для java - это аналог модуля php-интерпретатора в веб-сервере. Таким образом, когда пользователь в строке веб-браузера вводит адрес, этот запрос отправляется веб-серверу, веб-сервер понимает, что запрашивается сервлет, и передает запрос контейнеру сервлетов. После этого контейнер сервлетов выполняет сервлет, полученную html-страницу отправляет веб-серверу, а тот, в свою очередь, возвращает ее клиенту. Может ли контейнер сервлетов работать сам по себе, т.е. без веб-сервера? Такой как Tomcat – определенно может. И если мы хотим создать сайт, у которого не будет никаких других html-страниц, кроме как основанных на сервлетах, то контейнера сервлетов нам вполне достаточно. А вот если мы захотим комбинировать сайт из сервлетов и скажем php-страниц, то придется ставить веб-сервер. Причем не все веб-сервера имеют контейнер сервлетов в своем составе по умолчанию, зато почти все позволяют поставить его в качестве плагина. Поэтому если мы захотим запустить наш сайт на каком-нибудь хостинге в интернете, где, скорее всего, работает apache, то нам придется поинтересоваться у провайдера, подключен ли контейнер сервлетов.

Java EE

Есть, так называемый, JavaSE (Java Standard Edition). К этому понятию относятся все классы java, для использования которых нам достаточно их просто импортировать (например, java.util.Date) или даже этого делать не надо (например, String, т.к. он располагается в пакете java.lang). А есть Java EE (Java Enterprise Edition). Эти классы тоже принадлежат Sun/Oracle, но разница лишь в том, что их сложнее начать использовать в проекте. Простой строки import… будет недостаточно, т.к. проект компилироваться не будет. Для того чтобы исправить ситуацию, нужно будет найти файл библиотеки javaee.jar и подключить его в проект. Сделать это можно через свойства проекта в среде разработки. Часто говорят, что этот процесс подключения называется – прописать jar-ник в build path или classpath проекта.

Сервер приложений

Теперь представьте, что мы скомпилировали наш проект-сервлет, который использует Java EE. Все замечательно, но нам теперь нужно разместить наши скомпилированные классы в контейнере сервлетов. Допустим, сделали. Будет ли наше приложение работать. Ответ – нет. При обращении к сервлету полетят исключительные ситуации, что какие-то классы не найдены. Почему? Потому что компилятор-то мы «обманули», подсунув javaee.jar в classpath, т.е. компилятор увидел, что классы из Java EE на месте и успокоился, а вот контейнер сервлетов этих классов не видит, зато видит ссылки на них из нашего сервлета. Разрешима ли данная ситуация в рамках контейнера сервлетов. Конечно да, нужно просто в контейнере сервлетов в папку с нашим сервлетом добавить файл библиотеки javaee.jar. А теперь представьте, что таких проектов будет много и все они запущены в одном контейнере сервлетов Tomcat. Это значит, что в папку каждого сервлета придется копировать этот файлик jar. Это неудобно и неправильно. Ситуация разрешилась путем ввода понятия сервера приложения, в котором этот файлик уже давно лежит в единственном экземпляре, и все сервлеты могут к нему обращаться, а не иметь свою копию. На мой взгляд, очень удобно и логично. Естественно, весь сыр бор не из-за одно jar-файла (его я привел для примера) – таких файлов много. Но это не все, что дают нам сервера приложений. Сервера приложений могут сами держать соединения со многими ресурсами, например, с базой данных. При этом наш сервлет может сам такое соединение не открывать, а просто брать его из сервера приложений. В контейнере же сервлетов – это невозможно, т.к. контейнер – это, в определенной степени, урезанный сервер приложений. В контейнере сервлет должен всегда сам создавать коннекшены к базе. Как-то так… war-архив Что такое war-архив? WAR – это web-archive (веб-архив). На самом деле, это просто zip-файл, как и любой jar-ник. По сути, это всего лишь способ, чтобы наш веб-сайт, состоящий из множества веб-страниц, jsp-страниц и классов сервлетов запихать в один файлик формата zip. web.xml web.xml – это, так называемый, дескриптор развертывания. Это файл, в котором тупо описано, какой запрос строки веб-браузера на обработку какому классу-сервлету отправлять, чтобы контейнер сервлетов не запутался, какой сервлет за что отвечает. В целом, в Java очень модно описывать настройки во всяких xml-файлах, но в последнее время наметилась тенденция ухода от этой традиции. Как, спросите вы? А через аннотации. Классы-аннотации сами ничего не делают, они как раз и созданы только для того, чтобы всякие настройки (мета-данные) описывать не в отдельном xml-файле, а прямо по коду. Очень удобно. Однако сейчас наблюдается некая промежуточная стадия, когда часть настроек задана аннотациями, а часть через xml, и это может запутать, т.к. смотришь xml и видишь одну настройку, а по аннотациям стоит другая. Какая из них имеет высший приоритет? Кто знает…

Заключение

Написав сиё, я задумался, что такой беглый обзор никому не поможет, т.к. не содержит никакой конкретики и никаких примеров, но с другой стороны не стирать же написанное, поэтому пусть будет.
Комментарии (23)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
16 февраля 2021
Автор - молодец! Таких статей нужно больше, что бы вопросов было меньше... А то читаешь термины - а в голове пустота остается(терминам зацепиться не за что), прям нового не узнал из статьи, но структурировал и подтвердил свои разрозненные догадки))) в целом - огромнейщее спасибо за статью!
Виктор Уровень 24
18 февраля 2020
Порадовала статья) Смысловой нагрузки не много. Зато коротко и доступно) За заключение отдельный плюс в карму=)
Timur Уровень 9
24 апреля 2019
Только учусь и везде это непонятное слово сервлет, контейнеры, жуть короче. Лезешь в гугл и всякая кваказябра а не объяснения простым языком. Сейчас дошло, спасибо)
ABORMOT Уровень 24
16 декабря 2015
Сервера приложений могут сами держать соединения со многими ресурсами, например, с базой данных. При этом наш сервлет может сам такое соединение не открывать, а просто брать его из сервера приложений. В контейнере же сервлетов – это невозможно, т.к. контейнер – это, в определенной степени, урезанный сервер приложений. В контейнере сервлет должен всегда сам создавать коннекшены к базе. Как-то так…
Разве Tomcat не может держать пул коннекшнов к базе?
Вроде как может, в файле web-xml нужно прописать ресурсы + конигурационный файл context.xml для конфигурации соединения

Я неправ?
Goodwin Уровень 18
19 апреля 2015
Доброго дня! Что вы можете рассказать паттерне Front Controller?
provisota Уровень 33
10 апреля 2015
Спасибо за статью, и за комменты тоже!
Вроде бы вещи достаточно тривиальные и понятные, но у вас так хорошо получается раскладывать всё по полочкам =)
Буду и дальше следить за вашим блогом.
javaNub Уровень 8
6 апреля 2015
Дельная статья (плюсанул) Спасибо!!!
Только не понятен один момент — Есть преkрасная отточенная технология PHP.
Почему часто я вижу как юзают именно технологию сервлетов и иже с ними(особенно в банках)
С точки зрения юзера, какие отличительные особенности могут мотивировать его на изучение этих *влеттов?
Goodwin Уровень 18
6 апреля 2015
поясните, что такое artifacts? зачем их билдить в проекте?
grishin Уровень 27
6 апреля 2015
Что же представляет собой почти любой фронт-энд фреймфорк, к примеру, Apache Struts. Это просто набор классов, расширяющих базовый класс Servlet. Более ничего. Т.е. это просто другой способ создать тот же самый обычный сервлет.
Вот-вот, понасоздают понимаешь классов вагон и целую тележку, а джунам потом все изучай это :-)
Спасибо, было интересно почитать статью, т.к. уже имею представление о теме. Если до этого ещё не добрался, то конечно ничего понятно не будет :-)
Vakatsiienko Уровень 20
1 апреля 2015
Про пыху лучше бы и не вспоминали, только путает, т.к. далеко не каждый с пыхи сюда пришел. Ну и о том, что в после нету вообще никакой конкретики, лучше говорить сразу ;)
З.Ы. Слишком расплывчато, чтобы дискутировать. Единственное, что могу сказать это то, что мне кажется ошибкой называть сервлет веб-страницой, по крайней мере с точки зрения ООП, а это ведь самая основа всей разработки на джаве.