Допустим мы хотим написать web-server с rest-like API на java, но пока не знаем никаких фреймворков, стандартов и библиотек.
1. Socket
Первое, что мы можем сделать - реализовать полностью сами всю логику с нуля на сокетах.
Socket - это такое понятие из TCP протокола. Это некое гнездо, которое может принимать/отправлять пакеты данных по сети на определенном порту.
Нам нужно будет сделать примерно следующее:
* установка/завершение TCP соединений с клиентами
* поддержание пула соединений, чтобы сервер мог параллельно обрабатывать несколько запросов
* разбор http хедеров, кук, урлов
* и много других низкоуровневых механизмов, предполагающих изучение документации протоколов и сложного concurrency
На реализацию и поддержку этого кода могут уйти месяцы. Но даже после этого такой сервер будет значительно уступать существующим по производительности и стабильности.
В добавок бизнес-логика сервера скорее всего утонет в техническом коде, что еще больше усложнит поддержку.
2. Servlet API
Чтобы решить проблемы выше был изобретен стандарт Servlet API.
Самая главная часть API методе service() интерфейса javax.servlet.Servlet:
public void service(ServletRequest req, ServletResponse res)
Нам нужно всего лишь достать необходимые параметры / хедеры / и т д из параметра req и записать ответ / статус в res.
В нашем случае намного легче взять абстрактную реализацию этого интерфейса - HttpServlet
Примерно так:
И привязать этот сервлет к какому нибудь пути в XML:
Теперь, если открыть в браузере http://my-api.com/hello , увидим текст "Hello from servlet"
А как это работает?
Всю магию делает за нас «контейнер сервлетов». Это как раз та штука, которая реализует спецификацию сервлетов и предоставляет нам Servlet Api.
Самые распространенные:
* Tomcat
* Jetty
* Undertow
А схема примерно такая:
1. Мы пакуем наш код в специальный формат war и загружаем в контейнер
2. На каждый запрос к серверу по указанному пути сервер создает новый сервлет с нашим кодом
3. На каждый запрос выделяется собственный поток
Этот подход уже значительно упрощает разработку веб-сервера, но остались еще пара важных вещей, которые фреймворк мог бы делать за нас:
• сериализация/десериализация тела запроса и ответа (например, json <–> pojo)
• более гибкий маппинг урлов в методы (роутинг)
• и ещё куча более специфичных хотелок от безопасности, до транзакционности
Spring framework vs Jakarta EE
Тут нам на помощь приходят фреймворки с значительно большим уровнем абстракции. На момент написания записочки самыми популярными являются:
• Spring Framework
• Jakarta EE (ex Java EE)
Jakarta EE
Jakarta EE - это огромное количество стандартов и API типа JTA, CDI, JPA, JNDI и еще много-много. Эти api позволяют упростить разные спектры разработки веб-приложений.
Если контейнер сервлетов заодно реализует еще все эти стандарты, он называется "сервер приложений". Примеры:
• WildFly (ex JBoss)
• WebLogic (by Oracle)
• WebSphere (by IBM)
• TomEE (Tomcat c реализацией всех тех стандартов)
Схема работы сервера приложений почти не отличается от схемы работы контейнера сервлетов. Он просто добавляет еще много фреймворков, упрощающих разработку.
Spring Framework
В основе экосистемы спринга стоит DI. Это такая штука, которая позволяет удобно подсовывать одни объекты в другие. Ядро оказалось очень удобным и вокруг него выросла куча библиотек и фреймворков. Большинство из них имеют аналог в мире Jakarta EE. Примеры:
• spring web
• spring jdbc template
• spring security
• spring cloud
• spring data
Как работает spring framework?
1. Мы пишем код в виде простых классов (называются бинами bean)
2. Пишем код, который описывает какие бины нужно заинджектить в какие
3. Запускаем IoC контейнер спринга
4. IoC контейнер читает наш код и конфигурацию
5. По указаниям в конфигурации подсовывает инстансы одних классов в другие
6. Мы достаем из него нужные классы и запускаем на них методы
Как выбрать?
Jakarta EE в основном используют всякие интерпрайзы (типа банков) потому что они любят больших вендоров (типа IBM и Oracle) и море XML.
Хипстеры же предпочитают spring, потому что он больше для людей.
Конечно, это все вкусовщина. Я надеюсь, что в ближайшем будущем Jakarta EE еще составит достойную конкуренцию spring. Но покодив на обоих, я для себя выбрал spring. Поэтому дальше рассказ про него.
Spring Web
Так вот Spring Web - это веб фреймворк, построенный поверх Servlet API, чтобы еще больше упростить нам жизнь.
Пример кода:
Этот класс называется контроллер. Его методы соответствуют урлам нашего api. Когда клиент запросит http://my-api.ru/hello , выполнится метод getHello().
Мы описали все это с помощью аннотаций. Spring Web прочитает их и настроит сервлет как нужно.
Происходит это примерно так:
1. Спринг распарсил наши контроллеры и настроил специальный класс DispatcherServlet
2. На каждый запрос запускается DispatcherServlet
3. Он определяет, какой вызвать метод в каком контроллере
4. В нашем методе контролера отрабатывает бизнес логика
5. Ответ сериализуется (например в json)
Теперь мы всем довольны и можем реализовывать свое API, не думая ни о чем кроме бизнес логики.
Выводы:
1. Почти никогда не имеет смысла реализовывать логику веб-фреймворка самостоятельно - это долго и сложно
2. Большинство веб-фреймворков работает поверх Servlet API
3. Всегда полезно понимать, как работает твой любимый веб-фреймворк изнутри. Это помогает использовать его максимально эффективно и получать максимальное веселье от работы с ним