Всем привет! И снова данная статья является сугубо базовым познавательным обзором для новичков. Здесь не будет ничего сложного, поэтому тех, кто изголодался по сложным статьям, прошу сильно помидорами не закидывать)
Итак, допустим мы хотим написать 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 Frameword
В основе экосистемы спринг стоит DI. Это такая штука, которая позволяет удобно подсовывать одни объекты в другие. Ядро оказалось очень удобным и вокруг него выросла куча библиотек и фреймворков.
Примеры:
• spring web
• spring jdbc template
• spring security
• spring cloud
• spring data
Как работает spring framework?
1. Мы пишем код в виде простых классов (называются бинами bean)
2. Пишем код, который описывает какие бины нужно заинджектить
3. Запускаем IoC контейнер спринга
4. IoC контейнер читает наш код и конфигурацию
5. По указаниям в конфигурации подсовывает инстансы одних классов в другие
6. Мы достаем из него нужные классы и запускаем на них методы
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. Всегда полезно понимать, как работает твой любимый веб-фреймворк изнутри. Это помогает использовать его максимально эффективно и получать максимальное веселье от работы с ним