# Лекция 3-4

## Тема: Клиент-серверная архитектура приложения. Сокеты в Java. Технология Java Servlets. Проект Spring Boot. Быстрое создание приложения с помощью Spring Boot. Архитектура Spring-приложения (web layer, service layer, repository layer).

## Клиент-серверная архитектура

Сервер - компьютер или программа, которая управляет ресурсами (информация, файлы, база данных) называется сервером этого ресурса или просто сервером.

Архитектура "клиент-сервер" определяет общие принципы организации взаимодействия, где имеются серверы (узлы-поставщики некоторых специфичных функций и сервисов) и клиенты, (потребители этих сервисов).

Между клиентами и серверами должны быть установлены правила взаимодействия, которые называются протоколом взаимодействия или протоколом обмена. Каждая часть взаимодействует друг с другом, обмениваясь сообщениями в заранее согласованном формате.

{% hint style="info" %}
Более подробно про клиент-серверное взаимодействие читайте здесь - [http://bit.ly/2qmKbHk](http://bit.ly/2qmKbHk)
{% endhint %}

В рамках данного курса рассматривается так называемая "трехзвенная архитектура"

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-LtYAOdkAcnChZflt_QB%2F-LtYCdWC7V2S8XZsQ3q8%2Fimage.png?alt=media\&token=c332fc00-1ba6-476f-8f5a-9959d519e9f7)

Компоненты трехзвенной архитектуры:

* клиент - этот компонент отвечает за представление данных конечному пользователю;
* выделенный сервер приложений - здесь содержится бизнес-логика приложения;
* сервер БД - предоставляет запрашиваемые данные.

**Сервер приложений (application server)** – сервисная программа, которая обеспечивает доступ клиентов к прикладным программам, выполняющимся на сервере.

Большинство серверов приложений имеют в своем составе веб-сервер. Это означает, что сервер приложений может делать все, на что способен веб-сервер. Кроме того, сервер приложений имеет компоненты и функции для поддержки сервисов уровня приложения, таких как пул соединений, поддержка транзакций и так далее.

{% hint style="info" %}
Информация о сервере приложений - [http://bit.ly/2qt2Q4t](http://bit.ly/2qt2Q4t). \
Отличия веб-сервера и сервера приложений - [http://bit.ly/2qlUaNe](http://bit.ly/2qlUaNe)\
Подробнее про сервлеты и контейнеры сервлетов - [http://bit.ly/2Q9GAaP](http://bit.ly/2Q9GAaP)
{% endhint %}

## Технология Java Servlets

На заре развития интернета не существовало технологий для создания динамических веб-страниц. В то время сайт представлял собой набор статических заранее написанных и сверстанных страниц с помощью языка разметки HTML. Если владелец сайта хотел обновить информацию на страничке, он делал это непосредственно на своем компьютере, после чего загружал на сервер обновленную версию HTML-страницы.

Среди предложенных решений по созданию динамических страниц, одной из первых была технология **Java Servlets**. В то время это была революционная технология, которая позволяла расширить возможности веб-серверов на основе модели запрос-ответ (request - response). Технология сервлетов позволяла веб-серверам обрабатывать HTTP-запросы и динамически генерировать веб-странички в зависимости от HTTP-запроса.

{% hint style="info" %}
На данный момент актуальной версией технологии является версия 4.0, спецификацию технологии смотрите [здесь](https://jcp.org/en/jsr/detail?id=369).
{% endhint %}

Несмотря на почтенный возраст, технология сервлетов претерпела серьезные изменения для того, чтобы соответствовать современной технологии разработки веб-приложений. На данный момент, технология сервлетов является наиболее часто используемой технологией для обработки HTTP запросов/откликов. Кроме того, сервлеты являются базой для почти всех Java-фреймворков, которые работают с HTTP протоколом (JSF, Struts, Spring MVC, BIRT и так далее).

**Сервлет (Servlet)**, по сути, является классом Java, который используется для расширения возможностей сервером, предназначенных для размещения приложений. Сервлеты могут отвечать на запросы и генерировать отклики. Базовым классом для всех сервлетов является класс `javax.servlet.GenericServlet`. Этот класс определяет обобщенный, независимый от протокола сервлет.

Схема работы технологии сервлетов представлена на рисунке ниже

![Схема работы технологии Java Servlets](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-MVx2-CK9HFQVbZQ3sWz%2F-MVxREdkIBXJK22k7Oe6%2Fimage.png?alt=media\&token=96ef17cb-2662-4d49-85db-b8fa57a6cd4f)

1. клиент (например, веб-браузер) передает HTTP-запрос веб-серверу. В случае, если от веб-сервера требуется предоставить статический файл или какой-то ресурс (например, изображение), то он просто возвращает требуемый статический файл или ресурс;
2. если веб-сервер не может самостоятельно обработать HTTP-запрос (например, пользователь передает какие-то данные либо требуется предоставить динамическую страницу и так далее), веб-сервер передает этот запрос web-контейнеру (его еще называют servlet-контейнером);
3. контейнер определяет – какой сервлет может выполнить этот запрос, создает объекты классов `HttpServletRequest` и `HttpServletResponse`, создает thread, создает объект класса сервлета и передает ему объекты классов `HttpServletRequest` и `HttpServletResponse`;
4. Контейнер вызывает метод сервлета `service()`, который вызывает соответствующий HTTP-запросу метод (например, если запрос был **HTTP** **GET**, то будет вызван метод `doGet()`, подробнее этот вопрос будет разбираться далее), которому, в качестве аргументов, передает объекты классов `HttpServletRequest` и `HttpServletResponse`;
5. Соответствующий метод (например, метод `doGet()`) возвращает динамическую страницу внутри объекта класса `HttpServletResponse`, ссылку на который имеет контейнер;
6. После этого поток завершается, контейнер конвертирует объект класса `HttpServletResponse` в HTTP-отклик (HTTP response) и отдает его веб-серверу, который возвращает его клиенту.

### Фреймворк Spring

**Spring** – свободно-распространяемый легковесный фреймворк, призванный упростить разработку корпоративных и веб-приложений (можно использовать и для любых других типов приложений) на языке Java (является альтернативной стеку Jakarta EE).

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-LtaZ_4H5iU8wIgV5pDu%2F-Lta_quWkLgtNog-OVL5%2Fimage.png?alt=media\&token=b0cd5d93-2cd3-4637-a149-86dffe554d68)

В данный момент Spring представляет собой целый набор модулей, которые можно использовать выборочно для тех или иных проектов.

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-LtaZ_4H5iU8wIgV5pDu%2F-Lta_uvl51mwhOi_-HRH%2Fimage.png?alt=media\&token=05b995cf-7cd2-40b6-ba10-1936fcc9c2bd)

Дадим краткую характеристику **некоторым модулям** **Spring**:

* **Spring** **Core** – ядро платформы, предоставляет базовые средства для создания приложений — управление компонентами (бинами, beans), внедрение зависимостей, MVC фреймворк, транзакции, базовый доступ к БД. В основном это низкоуровневые компоненты и абстракции. По сути, неявно используется всеми другими компонентами;
* **Spring** **MVC** – обеспечивает архитектуру паттерна Model-View-Controller при помощи слабо связанных готовых компонентов для разработки веб-приложений;
* **Spring Data** – обеспечивает доступ к данным: реляционные и нереляционные БД, KV хранилища и т.п.;
* **Spring Cloud** – используется для микросервисной архитектуры;
* **Spring Security** – авторизация и аутентификация, доступ к данным, методам и т.п. OAuth, LDAP, и различные провайдеры.

### **Spring** **Boot**

Проект **Spring** **Boot** – решение, которое позволяет вам легко создавать полноценные приложения Spring, про которые можно сказать «просто запусти».

Spring Boot позволяет быстро создать и сконфигурировать (т.е. настроить зависимости между компонентами) приложение, упаковать его в исполняемый самодостаточный артефакт. Это то связующее звено, которое объединяет вместе набор компонентов в готовое приложение.

**Особенности** **Spring Boot:**

* создание полноценных Spring-приложений;
* встроенный сервлет-контейнер (Tomcat или Jetty);
* обеспечивает начальные pom-файлы для упрощения конфигурации Maven;
* используется автоконфигурация, где это возможно;
* используется принцип «**convention over configuration**». Для большинства конфигураций не нужно ничего настраивать.

Изучение фреймворка Spring лучше всего начать с установки требуемого программного обеспечения и разработки тестового приложения с помощью Spring Boot.

### Установка программного обеспечения

Для выполнения домашнего задания нам понадобится следующее программное обеспечение:

* JDK - [http://www.oracle.com/technetwork/java/javase/downloads/index.html](http://www.oracle.com/technetwork/java/javase/downloads/index.html);
* приложение Postman - [https://www.getpostman.com/downloads/](https://www.getpostman.com/downloads/);
* среда разработки, которая поддерживает Spring (например, IntelliJ IDEA Ultimate Edition или дистрибутив Eclipse под названием Spring Tool Suite –  [https://spring.io/tools](https://spring.io/tools)) либо любая другая IDE с поддержкой Java и Maven.

### Создание Spring Boot проекта

Существует несколько способов создать Spring Boot проект. Из наиболее простых способов можно выделить:

* генерация готового проекта на сайте [https://start.spring.io/](https://start.spring.io/) (проект **Spring Initializr**);
* создание проекта средствами IDE.

Создадим проект с помощью мастера Intellij IDEA. Создадим новый Spring Boot проект (выберите пункт Spring Initializr). Необходимо указать JDK, метаданные проекта, а также выбрать из списка модулей нужные нам модули Spring

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-Ltut0w3f3_7UxGZX6_8%2F-Ltuv4_Cp3iDk0fX5tjA%2Fimage.png?alt=media\&token=4f7fa4e9-ad7e-439c-8f8a-6a157ae2269c)

Для выполнения задания нам необходимо выбрать web-модуль. Панель выбранных компонентов будет иметь следующий вид:

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-Ltut0w3f3_7UxGZX6_8%2F-LtuvjzsUc8TFdmOFjF8%2Fimage.png?alt=media\&token=f0aca705-7e4d-490b-bd61-b3cf92bc9948)

После окончания работы мастера создания проектов, мы получим стартовый проект Spring Boot. Рассмотрим структуру проекта и обозначим ключевые файлы:

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-Ltut0w3f3_7UxGZX6_8%2F-Ltuw67XMok_w5URCw0W%2Fimage.png?alt=media\&token=721bfa1c-4c10-4737-8669-951db2cda65b)

* **HotelApplication.java** - стартовый класс Spring Boot приложения;
* **application.properties** - файл с настройками приложения. В нем можно переопределить настройки по умолчанию;
* **pom.xml** - POM-файл проекта. Используется сборщиком Maven.

**POM-файл** (Project Object Model) – это XML-файл, который содержит информацию о деталях проекта, и конфигурации для создания проекта на Maven. Он всегда находится в базовом каталоге проекта. Во время выполнения задач, Maven ищет pom-файл в базовой директории проекта. Он читает его и получает необходимую информацию, после чего выполняет задачи.

Корневым элементом является элемент **\<project>**. Внутри тега project содержится основная и обязательная информация о проекте.

**Зависимости (dependency)** – это те библиотеки, которые непосредственно используются в проекте для компиляции кода или его тестирования.

Мы создаем RESTful веб-службу с помощью Spring Boot, поэтому нам нужно «подтянуть» для нашего проекта различные Spring-модули (библиотеки с классами, jar-файлы).

В обычных проектах нам бы было необходимо добавлять каждую зависимость вручную, но Spring Boot позаботился о нас и предоставил нам своего рода «мета-зависимости». Смысл их в том, что Spring Boot понимает, что если вы создаете web-приложение то вам нужен примерно одинаковый набор jar-файлов, поэтому чтобы не писать каждый jar-файл отдельно, мы указываем одну зависимость, а она уже «подтянет» за нас другие отдельные зависимости для создания веб-приложения.

### Запуск приложения

Теперь давайте сразу запустим приложение. Убедимся, что приложение запущено успешно

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-Ltut0w3f3_7UxGZX6_8%2F-LtuyLsgdeSF_fZgF4sp%2Fimage.png?alt=media\&token=fc440ab3-9326-4ca8-867a-1305aecaff02)

перейдем в браузер и попробуем зайти на сайт.

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-Ltut0w3f3_7UxGZX6_8%2F-LtuykItBpm7_SPdrYfV%2Fimage.png?alt=media\&token=3b3859a2-1267-4344-8842-8741fdd2c7e6)

Как видите, Spring Boot приложение успешно запущено. Так как Spring Boot берет на себя большую часть рутинной работы по созданию и запуску приложения, давайте разберемся, что же происходит, когда мы запускаем приложение:

1.   Устанавливается конфигурация приложения по умолчанию;
2. Запускается **контекст приложения** **Spring** **(Spring** **application** **context)** – это контейнер для кода, который работает на сервере (службы, контроллеры и т.д.). Все приложения Spring имеют этот контекст, который запускается при запуске приложения. Spring Boot создает этот контекст при запуске приложения;
3. Выполняется сканирование пути к классам (class path scan). Чтобы добавить код в Spring Boot, необходимо создать свои классы и аннотировать их определенным образом. Например, если вы хотите добавить контроллер, вы создаете класс и аннотируете его с помощью аннотации @Controller и так далее. То есть, вы как бы помечаете ваши классы, что это контроллер, это сервис, это еще что-то. Spring сканирует эти классы и, в зависимости от нашего маркера, он работает с этими классами по-разному. То есть Spring сканирует ваш код и ищет классы с этими аннотациями (помимо маркеров, обычно в аннотациях содержатся другие метаданные, которые дают уточняющую информацию для Spring);
4. Запускается Tomcat-сервер. Мы как раз зашли на сервер через URL и получили страницу с ошибкой, так как на сервере не был предусмотрен обработчик запроса с таким URL. Мы не скачивали Tomcat и не устанавливали его – все за нас сделал Spring Boot.

### Структура enterprise-приложения Spring

Простое приложение Spring имеет трехслойную структуру:

* **Web** **layer** – верхний слой приложения. Он отвечает за обработку ввода пользователя и возврат корректного ответа. Также веб-слой отвечает за обработку исключений, которые могут выбрасываться в других слоях приложения. Так как веб-слой является точкой входа в приложение, он также отвечает за аутентификацию и является первой линией защиты приложения;
* **Service** **layer** – слой сервисов, находится ниже веб-слоя. Этот слой содержит сервисы приложения и инфраструктуры. Сервисы приложения предоставляют публичный API сервисного слоя. Они также отвечают за транзакции и авторизацию. Инфраструктурные сервисы содержат код для взаимодействия с внешними ресурсами, такими как файловая система, базы данных, почтовые сервера и так далее. Часто эти сервисы используются несколькими сервисами приложения;
* **Repository** **layer** – самый нижний слой приложения. Он отвечает за взаимодействие с используемыми хранилищами данных.

![](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-Ltut0w3f3_7UxGZX6_8%2F-LtuzU3rHAnsT1M8m9pd%2Fimage.png?alt=media\&token=9cbf73fe-db99-44cc-9063-e1ac298a2164)

##
