---
# System prepended metadata

title: Лабораторная №4 Веб

---

# Лабораторная №4 Веб

## REST

REST (RESTful) - это общие принципы организации взаимодействия приложения с сервером с помощью HTTP. Особенность REST в том, что сервер не запоминает состояние пользователя между запросами (stateless) - в каждом запросе передаётся информация, идентифицирующая пользователя и все параметры, необходимые для выполнения операции.

При этом стейтлесс дает свои преимущества:
* упрощается горизонтальное масштабирование тк не имеет значение куда (на какой сервер) придет запрос
* ну и если все данные в запросе есть, то в теории мы не идём в память за ними, то есть в теории может быть быстрее

Всё взаимодействие с сервером сводится к 4 операциям (это необходимый и достаточный минимум, в конкретной реализации типов операций может быть больше):

* получение данных с сервера (обычно в формате JSON, или XML)
* добавление новых данных на сервер
* модификация существующих данных на сервере
* удаление данных на сервере

Формат обмена данными: здесь нет никаких ограничений. JSON — очень популярный формат, хотя можно использовать и другие, такие как XML
Транспорт: всегда HTTP. REST полностью построен на основе HTTP.

> Антипод REST'а -- RPC
> 
> Удаленный вызов процедур (RPC) — это когда клиент вызывает исполнение блока кода на сервере. В то время как REST рассматривает всё как ресурсы, RPC рассматривает действия. Клиенты обычно передают имя метода и аргументы серверу и получают обратно JSON или XML.
> 
> Правила RPC:
> 
> * Вызовы API выполняются с помощью наиболее подходящего HTTP-глагола: GET для запросов только для чтения и POST для других.
> * асимметричность, то есть одна из взаимодействующих сторон является инициатором;
> * синхронность, то есть выполнение вызывающей процедуры приостанавливается с момента выдачи запроса и возобновляется только после возврата из вызываемой процедуры.

## Single Page Applications (SPA)

Одностраничное приложение — это веб-приложение или веб-сайт, использующий единственный HTML-документ как оболочку для всех веб-страниц и организующий взаимодействие с пользователем через динамически подгружаемые HTML, CSS, JavaScript, обычно посредством AJAX

Single Page Application – сокращенно SPA, в переводе на русский язык означает “Приложение одной страницы”. Другими словами SPA – это web-приложение, размещенное на одной web-странице, которая для обеспечения работы загружает весь необходимый код вместе с загрузкой самой страницы. Приложение такого типа появились сравнительно недавно, с началом эры HTML5 и SPA является типичным представителем приложений на HTML5.

Страница сайта, на котором размещены все ссылки на все CSS, и ссылки на скрипты, необходимые для работы SPA мы назовем “Web-страница”. Файл с такой странице обычно называется “index.html” (в ASP.NET MVC может быть index.cshtml или index.vbhtml или даже index.aspx) А страницы, которые переключает пользователь внутри одностраничного приложения называются “модули”.

#### Плюсы

1) Приложения на SPA отлично работают на устройствах как стационарных, так и мобильных. Создав одно приложение, вы получаете гораздо большую аудиторию пользователей нежели при использовании стандартного подхода.
(Создать мобильное приложение проще, потому что разработчик может повторно использовать один и тот же внутренний код для веб-приложения и собственного мобильного приложения.)

2) SPA существенно сокращает так называемые “хождения по кругу”, то есть загрузку одного и того же контента снова и снова. Если ваш портал (сайт) использует шаблон, то вместе с основным содержанием какой-либо страницы посетитель сайта обязательно загружает разметку шаблона.

3) SPA работает быстро, поскольку большинство ресурсов (HTML + CSS + Scripts) загружаются только один раз за время существования приложения. Только данные передаются туда и обратно.

5) Кэширование данных — приложение отправляет всего один запрос, собирает данные, а после этого может функционировать в offline-режиме.

#### Минусы

1) Плохая SEO оптимизация. SPA работает на основе javascript и загружает информацию по запросу со стороны клиента. Поисковые системы плохо могут имитировать данное поведение. Потому большинство страниц попросту недоступны для сканирования поисковыми ботами, поэтому продвижение подобного сайта будет сложнее.

2) Неактивный javascript. Некоторые пользователи отключают javascript в своих браузерах, а без него ваше приложение не будет работать.

3) Низкий уровень безопасности. (По сравнению с «традиционным» приложением, SPA менее безопасен. Благодаря межсайтовому скриптингу (XSS) злоумышленники могут внедрять клиентские скрипты в веб-приложение другими пользователями.)

Принципы любого фреймворка (о них поговорим позже), который реализует парадигму SPA должны придерживаться следующих понятий и определений:

- SPA поддерживает клиентскую навигации. Все “хождения” пользователя по модулям-страницам однозначно фиксируются в истории навигации, навигация при этом является “глубокой”, то есть если пользователь скопирует и откроет ссылку на внутреннюю модуль-страницу в другом браузере или окне, он попадет на соответствующую страницу.
- SPA размещается на одной web-странице, значит всё необходимое для работы сайта (портала) скрипты и стили должны быть определены в одном месте проекта – на единственной web-странице.
- SPA хранит постоянно состояние (важные переменные) работы клиента (клиентского скрипта) в кэше браузера или в Web Storage.
- SPA загружает все скрипты требующиеся для старта приложения при инициализации web-страницы.
- SPA постепенно подгружает модули по требованию.

#### Навигация в SPA

Можно имитировать наличие разных страниц, сделав разные урлы и в зависимости от этих урлов грузить те или иные компоненты.
Переходы пользователя по страницам возможны благодаря history api. В котором у нас есть специальные методы которые позволяют перемещение назад и вперёд по истории пользователя.

Основные методы объекта History:
1. window.history.length: Количество записей в текущей сессии истории
1. window.history.state: Возвращает текущий объект истории
1. window.history.go(n): Метод, позволяющий гулять по истории. В качестве аргумента передается смещение, относительно текущей позиции. Если передан 0, то будет обновлена текущая страница. Если индекс выходит за пределы истории, то ничего не произойдет.
1. window.history.back(): Метод, идентичный вызову go(-1)
1. window.history.forward(): Метод, идентичный вызову go(1)
1. window.history.pushState(data, title , url): Добавляет элемент истории.
1. window.history.replaceState(data, title, url): Обновляет текущий элемент истории

State это объект состояния, в котором хранится информация связанная со страницей.

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

## React

**React - это JS библиотека**, которая предназначена для создания пользовательских интерфейсов.

Предназначен в основном для создания одностраничных приложений или Single Page Application.

**React основан на компонентах.** То есть приложение разделено на некоторые инкапсулированный элемент. Каждый компонент предназначен для определенной цели. Например, отобразить имя, аватарку и статус работника, если брать пример рабочей социальной сети. В этом плане React похож на Vue.js
И главное удобство заключается в том, что компоненты можно переиспользовать. Это очень удобно, когда в интерфейсе много одинаковых элементов, которые не приходится писать каждый раз с нуля.

Еще одной особенностью является:

Cледующая - это **Virtual DOM**. DOM - объектная модель документа. У реакта достаточно интересное взаимодействие с DOM.
Каждое изменение DOM - достаточно дорогостоящая операция. Поэтому в реакте есть такая концепция как Virtual DOM. По сути изначально это полная копия DOM. Однако, если вы взаимодействуете с каким-нибудь элементом, реакт изменяет не реальный DOM, а только виртуальный. Далее он сравнивает виртуальный дом с реальным с помощью библиотеки ReactDOM - и если они различаются, то реакт изменяет только ту часть DOMа, где он различается с виртуальным. в каком-то смысле виртуальный дом - некоторая прослойка между вашим приложением и DOM.

> Есть два типа элементов - ReactComponentElement и ReactDOMElement.
> 
> ReactComponentElement - ссылка на соответствующую функцию(класс) этого компонента.
> ReactDOMElement - виртуальное представление DOM-элементов.

### Компоненты React. State & props. "Умные" и "глупые" компоненты.

#### Компоненты React
Проще всего описывать компонент как функцию - пример функции. Однако можно использовать и классы, но это достаточно устаревший подход. С точки зрения React - оба подхода эквивалентны.

Чтобы отрендерить элемент используем функцию ReactDom.render(element, document.getElementById(‘root’); 
Название компонента - всегда с большой буквы

```javascript
ReactDOM.render(
            <App/>,
    document.getElementById('root')
)
```

#### Жизненный цикл
1. инициализация — создание экземпляра класса компонента
1. монтирование — компонент вставляется в DOM
1. обновление — компонент обновляется новыми данными через состояние или свойства
1. размонтирование — компонент удаляется из DOM

У всех компонентов в реакте есть жизненный цикл.

![](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/lifecycleComponent.png)

**Updation:**
shouldComponentUpdate - говорим, следует отрисовывать заново элемент или нет

props - componentWillReceiveProps - перед тем, как обновялются props, предыдущее состояние props'ов можно сохранить с помощью этой функции

**Unmouting:**
componentWillUnmount - что-то хотим сделать перед размонтированием (pop up открылся и нужно закрыть pop up и закрыть красиво и накинуть анимацию)

### Props

```javascript
const EmployeeListItem = (props) =>
    <div>
        {props.name} - {props.status}
    </div>
);
```

```html
<EmployeeListItem name=”James King” status=”President and CEO”/>
```

Если нам нужно передатьк какие-либо данные в компонент, то сделать мы это можем через пропсы. Пропсы - это входные данные, которые мы передаем функции - пример.
Очень важное замечание - пропсы можно только читать. Другими словами, все реакт компоненты должны вести себя как чистые функции. Это правило ни в коем случае нельзя нарушать при написании React приложения. 

#### Чистая функция

Функция должна удовлетворять двум условиям, чтобы считаться «чистой»:

* Каждый раз функция возвращает одинаковый результат, когда она вызывается с тем же набором аргументов
* Нет побочных эффектов
> Побочные эффекты включают любые взаимодействия с внешней средой: изменения внешних переменных и входных параметров (в случае их передачи по ссылке, а не по значению), HTTP-вызовы, запись на диск, вывод на экран.

За счет этого чистые функции позволяют избегать баги который появляются только при определененных условиях.

* Их просто тестировать. Достаточно передать на вход функции нужные параметры и посмотреть ожидаемый выход.
* Их безопасно запускать повторно, что особенно актуально в асинхронном коде или в случае многопоточного кода.
* Их легко комбинировать, получая новое поведение без необходимости переписывать программу (подробнее далее по курсу).

#### State

```javascript
const EmployeeListItem = (props) =>
const [age, setAge] = useState(1) //Задается начальное состояние
<div>
{props.name} - {props.status}
<br/>
{age} //Будет выведено: 1
</div>
);
```

Компонент может хранить в себе свое состояние и изменять его. В функциональных компонентах для объявления переменной состояния используется хук useState. Хук - это специальная функция, расширяющая возможности функциональных компонентов. Хуки можно использовать только внутри функциональных компонентов.

Состояние компонента меняется только через предоставленную функцию, так как реакт может сам заменить значение переменной, если изменить ее напрямую, то он не будет в курсе изменений.

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

Так же в компонентах есть возможность работать с циклами и обрабатывать события:
> 
> **Events**
> Работа с событиями - пример. e - синтетическое событие. Не нужно добавлять addEventListener. Просто указываем аттрибут onEvent и обработчик.
> 
> **Циклы**
> ```
> const List = () =>
>     <div>
>         {[1,2,3].map((el,index)=><span key={index}>{el}</span>)}
>     </div>
> ```
>     
> Работа с циклами в реакте аналогично обычному javascript - пример рендера несколько элементов.
>
> #### React-router
> 
> React-router вынесен в отдельную библиотеку. Она позволяет реализовывать навигацию между компонентами.
> 
> ![](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/react-router.png)

## Redux

![](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/redux.png)

Redux - хранилище для всего нашего приложения и мы можем из любого компонента получить состояние переменной, который находится в общем хранилище и подписаться на ее изменение, либо кинуть событие на ее изменение

**Важная особенность Redux:**
Данные напрямую в store обновить НЕЛЬЗЯ, чтобы обновить данные, мы отправляем action, который кидает запрос на обработку какого типа был action, и только потом изменяется значение в store

Особенности
* Общее, одно состояние данных, доступное из любого компонента
* Состояние изменяется только с помощью action, но не напрямую
* В компоненте можно подписаться на изменения определенного значения
* Компоненты могут иметь свое состояние(state), но только если оно важно только для данного компонента

#### Store

Похож на **state** компонента, только в отличии от state, он глобальный

Объект, который содержит состояние приложения и является уникальным.

Является неизменяемым - обновляется путем создания нового объекта. (удаляем прошлое значение)

const store = createStore( initialState, reducer)

* getState()
* dispatch(action) - генерация события
* subscribe(listener) - подписка на изменения
* replaceReducer(nextReducer)

#### Reducer

Это чистая функция, которая вычисляет новое состояние.

Мы отправляем ей действие, после чего проверяется тип действия.

```javascript
function counterReducer(state = initialState, action) {

if (action.type === 'counter/increment') {
return {
...state,
value: state.value + 1
}
}    

return state
}
```
Возвращаем дефолтное состояние стейта, так как он проходит еще одну итерацию

#### Action
Некоторое событие, которое должно привести к изменению состоянию.

С точки зрения js - это любой объект, имеющий идентификатор события (type)

```javascript
Action передается в reducer

const addToDo = (name) => ({
    type: ‘ADD_TO_DO’,
    payload: { name }
})
```
#### Dispatch
Функция redux, которая генерирует события.

dispatch(addToDo);

### Redux схема
![](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/reduxScheme.png)

#### Middleware
Главная их суть - принять входные данные действия, обработать и отправить дальше. Часто используются для работы с api

Например, мы хотим, чтобы при клике на кнопку отправился запрос на сервер, после запроса на сервер в зависимости от ответа мы обновили состояние store. Тут и используется middleware. Мы синхронно отправляем запрос, ожидаем ответа, в зависимости от ответа (состояния промиса) она вызывает опрделенный action

![](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/middleware.png)

---

## Angular: архитектура и основные принципы разработки приложений.

Angular - это JS фреймворк, является наследником библиотеки AngularJS. Прежде всего нацелен на разработку SPA приложений.

#### Особенности Angular

- Приложения состоят из модулей (наследники класса NgModules) 
- При этом модули обеспечивают контекст для компонентов (components)
- А из компонентов строятся представления (views)
- Ну а сами компоненты взаимодействуют с сервисами (элементы, реализующие логическую составляющую нашего фронта) (services)
    > с помощью DI

> ### Архитектура приложения на базе Angular
> 
> ![alt text](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/architectureAngular.png)
> 
> - Шаблон и комонент циклически обмениваются (путем биндинга пропертей и событий)
> - В компонент встраиваются сервисы путем использования Injector'a (он отвечает за DI в Angular)
> - Template (шаблон) использует метаданные заданной директивы, связывая себя с пропертями.

## Angular: модули, компоненты, сервисы и DI.

### Модули

- Каждый модуль обеспечивает контекст компиляции для одного или группы компонентов
- Модули могут связывать компоненты с сервисами, необходимыми для работы этих компонентов
- Группировка компонентов по модулям происходит на усмотрение разработчика
- Модули могут ссылаться друг на друга (возможны импорт и экспорт модулей)
> - Могут быть использованы для реализации ленивой загрузки (загрузка по требованию) lazy loading
> - Каждое приложение обязательно включает в себя корневой модуль (root module) под названием AppModule (файл app.module.ts)

#### Структура модуля

- Каждый модуль - класс TS с декоратором @NgModule() (декоратор - подобие аннотации)
- Содержит секции
    - declarations - компоненты, директивы, фильтры, содержащиеся в этом модуле
    - exports - то, что объявлено в этой секции, будет видно и доступно для использования в других модулях
    - imports - список внешних модулей, содержимое секции exports которых используется в текущем модуле
    - providers - сервисы, реализованные в этом модуле, видимые в глобальном контексте приложения

#### Создание модуля приложения

Приложение Angular состоит из модулей. Модульная структура позволяет легко подгружать и задействовать только те модули, которые непосредственно необходимы. И каждое приложение имеет как минимум один корневой модуль. 

```typescript=
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';
import { AppComponent }   from './app.component';
@NgModule({
    imports:      [ BrowserModule, FormsModule ],
    declarations: [ AppComponent ],
    bootstrap:    [ AppComponent ]
})
export class AppModule { }
```
Этот модуль, который в данном случае называется AppModule, будет входной точкой в приложение.

С помощью директив import здесь импортируется ряд нужных нам модулей. Прежде всего, это модуль NgModule. Для работы с браузером также требуется модуль BrowserModule. Так как наш компонент использует элемент input или элемент формы, то также подключаем модуль FormsModule. И далее импортируется созданный ранее компонент.


### Компоненты
- У всех компонентов внутри одного модуля общий _контекст компиляции_. При компиляции они друг друга видят и компилятор видит все компоненты этого модуля
- Каждый компонент - отдельный класс
- Контролирует область экрана, называемую представлением (div-чик или блок)
- Ангуляр управляет жизненным циклом компонентов

#### Создание компонента:
Каждое приложение Angular имеет как минимум один компонент. 
В начале файла определяется директива import, которая импортирует функциональность различных модулей. 

Далее собственно идет функция-декоратор @Component, которая ассоциирует метаданные с классом компонента AppComponent. В этой функции, во-первых, определяется параметр selector или селектор css для HTML-элемента, который будет представлять компонент. Во-вторых, здесь определяется параметр template или шаблон, который указывает, как надо визуализировать компонент. В этом шаблоне задана двусторонняя привязка с помощью выражений `[(ngModel)]="name"` и `{{name}}` к некоторой модели name.

И в конце собственно экспортируется класс компонента AppComponent, в котором как раз определяется переменная name - в данном случае это пустая строка.

**Компонент:**

```typescript=
import { Component } from '@angular/core';
     
@Component({
    selector: 'my-app',
    template: `<label>Введите имя:</label>
                 <input [(ngModel)]="name" placeholder="name">
                 <h1>Добро пожаловать {{name}}!</h1>`
})
export class AppComponent { 
    name= '';
}
```

### Представление

- Представление (views) формируется из компонентов и их шаблоны (templates)
- Каждый компонент содержит корневое представление, с которого начинается рендеринг интерфейса (host view)

### Директивы

Директивы определяют набор инструкций, которые применяются при рендеринге html-кода. 
> Директива представляет класс с директивными метаданными. В TypeScript для прикрепления метаданных к классу применяется декоратор @Directive.

В Angular есть два типа директив:
* **Атрибутивные**: они изменяют поведение уже существующего элемента, к которому они применяются. Например, ngModel, ngStyle, ngClass
* **Структурные**: они изменяют структуру DOM с помощью добавления, изменения или удаления элементов html. Например, это директивы ngFor и ngIf
> * **Компоненты**: компонент по сути также является директивой, а декоратор @Component расширяет возможности декоратора @Directive с помощью добавления функционала по работе с шаблонами.

![alt text](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/directives.png)

### Метаданные компонента

- Задаются с помощью декоратора @Component
- Сообщает рантайму о том, что это за компонент и где искать его составляющие

### Фильтры

 ![alt text](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/pipes.png)


### Сервисы и DI

Сервисы в Angular это набор классов, которые выполняют некоторые специфические задачи, например, логгирование, работу с данными и т.д.

В отличие от компонентов и директив сервисы не работают с представлениями, то есть с разметкой html, не оказывают на нее прямого влияния. Они выполняют строго определенную задачу.

Стандартные задачи сервисов:

* Предоставление данных приложению. Сервис может сам хранить данные в памяти, либо для получения данных может обращаться к какому-нибудь источнику данных, например, к серверу.
* Сервис может представлять канал взаимодействия между отдельными компонентами приложения
* Сервис может инкапсулировать бизнес-логику, различные вычислительные задачи, задачи по логгированию, которые лучше выносить из компонентов.

#### Провайдеры для сервисов

 ![](https://raw.githubusercontent.com/whoismuch/Laba4_WEB/master/resources/providers.png)

Dependency Injection позволяет передавать по приложению любые данные, преобразовывать и переопределять их в нужных частях.

---

### DI - осуществляется элементом Angular Injector' ом

- Компоненты могут использовать сервисы с помощью DI
- Для того, чтобы класс можно было использовать с помощью DI, он должен содержать декоратор @Injectable()

#### Основные принципы реализации DI

- Приложение содержит как минимум один глобальный Injector, который занимается DI (Injector'ов может быть >1)
- Injector создает зависимости и передает их экземпляры контейнеру (container)
- Провайдер (provider) - это объект, который сообщает Injector'у, как получить или создать экземпляр зависимости
- Обычно провайдером сервиса является сам его класс 
- Зависимости компонентов указываются в качестве параметров их конструкторов 



## Angular: шаблоны страниц, жизненный цикл компонентов, подключение CSS.

### Шаблоны и представления

- Представление (view) компонента задается с помощью шаблона (template) - та самая разметка, которая будет сформирована при просмотре компонента (в браузере)
- Представления часто группируются иерархически (складываются друг в друга)
- Компонент может содержать иерархию представлений (view hierarchy), которая содержит встроенные представление (embedded views) из других компонентов

#### Связь

Связь между шаблоном и компонетом работает в обе стороны:
- Шаблон(реализация компонента) отображает данные с компонента через property binding ({{hero.name}})
- Компонент принимает данные шаблона через event binding ((click) = "selectHero(hero)")

##### Три вида связи

 ![alt text](https://github.com/whoismuch/Laba4_WEB/blob/master/resources/3typesOfBinding.png?raw=true)




## Angular: клиент-серверное взаимодействие, создание, отправка и валидация данных форм.

### Взаимодействие с back-end'ом

 ![alt text](https://github.com/whoismuch/Laba4_WEB/blob/master/resources/interactionWithBackend.png?raw=true)

### Использование HttpClient

 ![alt text](https://github.com/whoismuch/Laba4_WEB/blob/master/resources/UsageHttpClient.png?raw=true)

### Пример получения JSON с сервера 

 ![alt text](https://github.com/whoismuch/Laba4_WEB/blob/master/resources/GettingJsonFromServer.png?raw=true)

 ![alt text](https://github.com/whoismuch/Laba4_WEB/blob/master/resources/GettingJsonFromServer2.png?raw=true)
 
 
 
 
 
 
---

## Spring Data (пахнет плохо)

Spring Data — дополнительный удобный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение, в каких то случаях для этого будет достаточно объявить интерфейс и метод в нем, без имплементации.

Задача Spring Data состоит в том, чтобы предоставить знакомую и последовательную модель программирования на основе Spring для доступа к данным, сохраняя при этом особые черты базового хранилища данных.

Он упрощает использование технологий доступа к данным, реляционных и нереляционных баз данных.

Что умеет: https://habr.com/ru/post/435114/#:~:text=Spring%20Data%20%E2%80%94%20%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9%20%D1%83%D0%B4%D0%BE%D0%B1%D0%BD%D1%8B%D0%B9%20%D0%BC%D0%B5%D1%85%D0%B0%D0%BD%D0%B8%D0%B7%D0%BC,%D0%9C%D0%B5%D1%82%D0%BE%D0%B4%D1%8B%20%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2%20%D0%B8%D0%B7%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8%20%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%B0

data access object (DAO) — абстрактный интерфейс к какому-либо типу базы данных или механизму хранения. Определённые возможности предоставляются независимо от того, какой механизм хранения используется и без необходимости специальным образом соответствовать этому механизму хранения.

В стеке Spring существует проект Spring Data, реализующий большую часть тривиальных задач и упрощающий работу с источниками данных. В качестве источников данных могут использоваться как стандартные реляционные базы данных, так и NoSQL-хранилища вроде MongoDB или Redis.  
Spring Data - это проект, управляемый Spring, который направлен на обеспечение согласованного уровня доступа к данным для различных хранилищ данных, от реляционных баз данных до баз данных без sql.  
Spring Data НЕ является спецификацией или стандартом . Данные Spring - это абстракция . Это зонтичный проект, в котором есть несколько модулей (например, spring-data-redis, spring-data-mongo и т. Д.) И основной модуль, называемый spring-data-commons. Эта абстракция пытается обеспечить согласованность между способами доступа к данным в нескольких хранилищах данных.

В мире Java EE стандартом дефакто для работы с базами данных является JPA (Java Persistence API). Spring Data JPA, будучи частью Spring Data, реализует взаимодействие с реляционными СУБД, основываясь на JPA.

## Spring Data JPA

Spring Data JPA  является одним из многих  Spring Data  проектов и направлено в направлении обеспечения согласованности в доступе к данным для реляционных хранилищ данных. Многие люди считают Spring Data JPA реализацией JPA. На самом деле это ложь. Spring Data JPA использует реализацию JPA по умолчанию, называемую Hibernate . Реализация JPA по умолчанию является настраиваемой, и при желании мы можем использовать и другие реализации.

### Что такое Spring Data JPA, если не реализация JPA?
Точнее говоря, Spring Data JPA - это надстройка для JPA. он предоставляет структуру, которая работает вместе с JPA и обеспечивает полную абстракцию на уровне доступа к данным в проекте.

Spring Data JPA включает в себя концепцию  репозиториев JPA  - набор  интерфейсов,  которые определяют методы запроса . Repository и Entity Bean представляют уровень DAO в приложении. Больше не нужно писать собственные запросы. Иногда нам нужно писать запросы или их часть, но это запросы JQL, а не собственные запросы к базе данных.

 ____
 
 Spring Data is a high level SpringSource project whose purpose is to unify and ease the access to different kinds of persistence stores, both relational database systems and NoSQL data stores.  
 Spring Data - это высокоуровневый проект SpringSource, целью которого является унификация и упрощение доступа к различным типам хранилищ постоянства, как системам реляционных баз данных, так и хранилищам данных NoSQL.
 
 
 ![alt-text](resources/SpringData.png)
 
 Со всеми типами постоянных хранилищ ваши репозитории (также известные как DAO или объекты доступа к данным) обычно предлагают операции CRUD (создание-чтение-обновление-удаление) для объектов одного домена, методов поиска, сортировки и разбивки на страницы. Spring Data предоставляет универсальные интерфейсы для этих аспектов (CrudRepository, PagingAndSortingRepository), а также конкретные реализации хранилища сохраняемости.
 
 Хотя объекты-шаблоны мощные, мы можем добиться большего. В репозиториях Spring Data вам нужно только написать интерфейс с методами поиска, определенными в соответствии с заданным набором соглашений (которые могут варьироваться в зависимости от типа используемого вами хранилища постоянства). Spring Data предоставит соответствующую реализацию этого интерфейса во время выполнения. Например:
 
 ```java
public interface UserRepository extends MongoRepository<User, String> { 
        @Query("{ fullName: ?0 }")
        List<User> findByTheUsersFullName(String fullName);
        List<User> findByFullNameLike(String fullName, Sort sort);
}
...
Autowired UserRepository repo;
```
---

## АОП Аспекто ориентированное программирование

Идея АОП заключается в выделении так называемой сквозной функциональности. Т.е. есть функциональность которая затрагивает несколько модулей, но она не имеет прямого отношения к бизнес логике, и ее хорошо бы вынести в отдельное место.

 Join point — следующее понятие АОП, это точки наблюдения, присоединения к коду, где планируется введение функциональности.
 
 
## Spring Core

 Spring -- универсальный фреймворк с открытым исходным кодом для Java-платформы.


Spring можно рассматривать как коллекцию меньших фреймворков. Большинство этих фреймворков может работать независимо друг от друга, но они обеспечивают большую функциональность при совместном их использовании. Среди них можно выделить: 

* Фреймворк доступа к данным: работает с системами управления реляционными базами данных на Java-платформе, используя JDBC- и ORM-средства и обеспечивая решения задач, которые повторяются в большом числе Java-based environments.
* Фреймворк управления транзакциями: координация различных API управления транзакциями и инструментарий настраиваемого управления транзакциями для объектов Java.
* Фреймворк MVC: каркас, основанный на HTTP и сервлетах, предоставляющий множество возможностей для расширения и настройки (customization).
* Фреймворк аутентификации и авторизации: конфигурируемый инструментарий процессов аутентификации и авторизации, поддерживающий много популярных и ставших индустриальными стандартами протоколов, инструментов, практик через дочерний проект Spring Security (ранее известный как Acegi).
* Тестирование: каркас, поддерживающий классы для написания модульных и интеграционных тестов.
* Inversion of Control-контейнер: конфигурирование компонентов приложений и управление жизненным циклом Java-объектов.
* Фреймворк аспектно-ориентированного программирования: работает с функциональностью, которая не может быть реализована возможностями объектно-ориентированного программирования на Java без потерь.

## Spring Security 

Как и все Spring проекты, настоящая сила Spring Security в том, что он может быть легко дополнен нужным функционалом.



Спринг секьюрити состоит из 8 модулей:
- ACL (Acscess control list)
    По факту это возможность использования списка разрешений прикрепленных к пользователю в зависимости от его роли и не только
- CAS Client (Сервер аутендификации)
    Обеспечивает интеграцию с централизованной службой аутендификации
- Configuration
    Обеспечивает поддержку пространства имен xml
- Core
    Основные классы и интерфейсы, относящиеся к аутентификации и авторизации пользователей, а также к обслуживанию контекста безопасности.
    Сервис для создания безопасных случайных токенов.
    Репозиторий аутентификации на основе JDBC.
    И репозиторий проверки подлинности в памяти.

- LDAP (light weight directory acscess protocol)
    Обеспечивает поддержку аутендификации с использование облегченного протокола доступа к каталогу
- OpenID
    Обеспечивает интеграцию с децентрализованной службой аутендификации
- Tag Library
    Представляет из себя теги жсп для обеспечения безопасности на уровне представления (те веб страничек)
- Web
    Обеспечивает поддержку безопасности в веб приложениях с применением фильтров

**Минимально** должны быть включены в проект модули **Core** и **Configuration** для того чтобы обеспечить работу спринг секьюрити

При этом спринг секьюрити использует возможности спринга и 
использует поддержку внедрения зависимостей и АОП.

Спринг секьюрити позволяет внедрять защиту как на уровне веб запросов так и на уровне методов. 

Для ограничения доступа на уровне веб запросов он использует сервлет фильтры. 

А для обеспечения безопасности на уровне вызовов методов с использованием АОП спринг секьюрити представляет объекты обертки и позволяет применять советы гарантирующие авторизацию пользователя

СС представляет поддержку такого удобного инструмента как OAuth.

![](https://i.imgur.com/V7xrBk7.png)

Для спринг секьюрити веб у нас есть дефолтная реализация страницы логина, но при этом мы можем написать свою и использовать ее.

Конфигурировать спринг секьюрити мы можем при помощи соотв хмл файл и при помощи аннтоаций.





Возможности

* Комплексная и расширяемая поддержка как аутентификации, так и авторизации
* Защита от атак на сервер
* Интеграция с Servlet API
* Интеграция с Spring Web MVC при необходимости

CSRF-атаки основаны на длительных куки-файлах аутентификации. После входа в систему или иного определения в качестве уникального посетителя сайта этот сайт, скорее всего, оставит файл cookie в браузере. Без явного выхода из системы или удаления этого cookie-файла он может оставаться действительным в течение некоторого времени.

Другой сайт может злоупотребить этим, если браузер отправляет (межсайтовый) запрос на сайт, подвергающийся атаке. 


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

Доступ к контексту безопасности можно получить в любой момент, из его держателю SecurityContextHolder.


## EJB

EJB — технология разработки серверных компонентов,
реализующих бизнес-логику. Ну либо некоторый конкретный программный компонент (бин) Enterprise JavaBean, который является частью технологии EJB и содержит в себе некоторую бизнес-логику. Получается этот термин имеет 2 значения.

Как технология EJB применяется когда требуется в приложении ряд некоторых сервисов такие как:
* поддержка сохранности данных (persistence): данные должны быть в сохранности даже после остановки программы. Чаще всего достигается с использованием базы данных;
* поддержка параллельного изменения данных и многопоточность;
* поддержка [событий](https://hackmd.io/S10B83uHSa-_7R39z9ClBQ#%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D1%8F-%D0%B2-EJB) (можно на стороне сервера кидать и обрабатывать события)
* безопасность и ограничение доступа к данным;
> * поддержка именования и каталогов (JNDI);
> * поддержка автоматизированной установки на сервер приложений;
> * удалённый доступ.
> * поддержка распределенных транзакций (с помощью
JTA).

> Компонентная модель EJB:
> 
> - EJB-компоненты инкапсулируются контейнером.
> - Контейнер предоставляет клиентам проксиобъекты (proxy objects) для доступа к EJB компонентам.
> - Прокси-объекты реализуют бизнес-интерфейсы
> (Business Interfaces).
> - Клиенты вызывают методы бизнесинтерфейсов.

Ну а сами Enterprise Java Beans делятся на 3 типа:

* Message Beans (бины, управляемые сообщениями);
* Entity Beans (объектные бины) — определены в спецификации JPA (Java Persistence API) и используются для хранения данных;
* Session Beans (cессионные бины).
    * stateless (без состояния);
    * stateful (с поддержкой текущего состояния сессии);
    * singleton (один объект на все приложение; начиная с версии EJB 3.1).

Жизненным циклом бинов управляет EJB-контейнер (в составе
сервера приложений).

**Sessions Beans:**

Они инкапсулируют в себе бизнес-логику, которую клиент может программно вызвать посредством вызова методов этого бина. 

> Вызов метода может выполнить:
> * локально, другим классом в той же JVM, что и сессионный бин;
> * удаленно, по сети, из другой JVM, с помощью технологии Java RMI (Remote Method Invocation).

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

> - Предназначены для синхронной обработки вызовов.
> - Вызываются посредством обращения через API.
> - Могут вызываться локально или удалённо.
> - Могут быть endpoint'ами для веб-сервисов.
> - CDI — аннотация @EJB.
> - Не обладают свойством персистентности. (Персистентность в программировании означает способность состояния существовать дольше, чем процесс, создавший его)
> - Можно формировать пулы бинов (за исключением @Singleton).
 
**Stateless Session Beans:**

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

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

> - Не сохраняют состояние между последовательными обращениями клиента.
> - Нет привязки к конкретному клиенту.
> - Хорошо масштабируются.
> - Объявление — аннотация @Stateless.
> 
```java
package converter.ejb;
import java.math.BigDecimal;
import javax.ejb.*;
@Stateless
public class ConverterBean {
 private BigDecimal yenRate = new BigDecimal("83.0602");
 private BigDecimal euroRate = new BigDecimal("0.0093016");
 public BigDecimal dollarToYen(BigDecimal dollars) {
 BigDecimal result = dollars.multiply(yenRate);
 return result.setScale(2, BigDecimal.ROUND_UP);
 }
 public BigDecimal yenToEuro(BigDecimal yen) {
 BigDecimal result = yen.multiply(euroRate);
 return result.setScale(2, BigDecimal.ROUND_UP);
 }
}
```

**Stateful Session Beans:**

 Stateful Session Beans сохраняют информацию о своем состоянии между обращениями к нему от одного и того же клиента и завершают свое существование по явному запросу от клиента. Достигается это за счет того, что stateful бины уникальны для каждого клиента. Stateful бины также уничтожаются, когда клиент завершает свою работу.

> - «Привязываются» к конкретному клиенту.
> - Можно сохранять контекст в полях класса.
> - Масштабируются хуже, чем @Stateless.
> - Объявление — аннотация @Stateful.

```java
@Stateful
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 20)
public class CartBean implements Cart {
@PersistenceContext(unitName = "pu", type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
private List products;
@PostConstruct
private void initializeBean(){
products = new ArrayList<>();
}
@Override
public void addProductToCart(Product product) {
products.add(product);
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void checkOut() {
for(Product product : products){
entityManager.persist(product);
}
products.clear();
}
}
```
**Singleton Session Beans:**

Singleton бины одиночки инициируются один раз за время существования приложения и существуют все время "жизни" приложения. Такие бины разрабатываются для ситуаций, в которых одно состояние должно быть разделено между всеми клиентами.

Как и со stateless бинам, в бинах одиночках разработчику необходимо следить за организацией потокобезопасной среды внутри бина. 

- Контейнер гарантирует существование строго одного экземпляра такого бина.
> - Объявление — аннотация @Singleton.
> + Один корпоративный компонент должен быть доступен нескольким потокам одновременно. 
> + Приложение нуждается в корпоративном Бобе для выполнения задач на запуск и завершение работы приложения.

--
Требования к классам Session Beans:

- Должен быть public классом верхнего уровня.
- Не должен быть final и/или abstract.
- Должен иметь public конструктор без
параметров.
- Не должен переопределять метод finalize().
- Должен реализовывать все методы бизнесинтерфейса(-ов).

--

В плюс к этому ещё есть пулы экземпляров бинов. 

Так как клиенты обращаются к проксям, реализующим бизнес-интерфейс, а с реальными объектами бинов дел не имеют, с их жизненным циклом можно вытворять разные штуки. Вот что происходит для каждого из трёх видов сессионных бинов:
- Stateful - у каждого клиента своя прокси, ведущая на свой и только свой экземпляр бина, потому что клиенту важно состояние его бина
- Stateless - у каждого клиента один и тот же интерфейс, который каким-то образом уводит пользователя к одному из экземпляров бина из пула
- Singleton - единый интерфейс и единый экземпляр заставят вас поразвлекаться с concurrency

--

**Message driven beans** 

Как и сессионные бины реализуют некоторую бизнес-логику. Но у них есть одно важное отличие. Клиенты никогда не вызывают методы напрямую. Такие бины чаще всего выступают в роли слушателей JMS (Java Message Service) сообщений и служат для организации асинхронного обмена сообщениями между частями системы.

```java
@MessageDriven(mappedName = "jms/TestQueue")
public class MessageDrivenEjbExample implements MessageListener {

    @Resource
    private MessageDrivenContext messageDrivenContext;

    public void onMessage(Message message) {
        try {
            if (message instanceof TextMessage) {
                TextMessage msg = (TextMessage) message;
                msg.getText();
            }
        } catch (JMSException e) {
            messageDrivenContext.setRollbackOnly();
        }
    }

}
```

> Аннотация @EJB служит для CDI и предоставляет клиентам не сам объект, а прокси, через который можно получить доступ к методам бизнес-интерфейсов. Может осуществляться доступ как к локальным, так и удаленным (в другой JVM) объектам.
> 
> **Stateless or Singleton:**
> 
> Я бы выбрал Stateless - сервер может генерировать множество экземпляров bean-компонента и обрабатывать входящие запросы параллельно.
> 
> Синглтон звучит как потенциальное узкое место - значение @Lock по умолчанию - @Lock (WRITE), но может быть изменено на @Lock (READ) для компонента или отдельных методов.
> 
> @Stateless позволит вам иметь несколько копий, готовых для обработки в JVM (столько, сколько позволяет память и размер пула), где, как @Singleton, в JVM есть только одна копия, даже если одна может поддерживать несколько параллельных потоков, работающих против нее.
> 
> С точки зрения производительности @Singleton было бы лучше, при условии, что используемые ресурсы позволяют длительный доступ. Однако в распределенной среде иногда происходят плохие вещи, например, могут выйти из строя ссылки базы данных или сети.
> 
> С @Stateless бином доступ более недолговечный. Кроме того, в случае сбоя он просто возродится и попытается установить новое соединение с ресурсом. Если что-то подобное происходит с синглтоном, то синглтон должен обработать его, не требуя перезапуска приложения, потому что @PostConstruct вызывается только один раз для каждой JVM.
> 
> Я бы предпочел немного отказоустойчивости по сравнению с производительностью в большинстве ситуаций, особенно в системах, которые я не контролирую.
> 
## Отличие Spring от JavaEE

Конкурентном Java EE считается Spring Framework. Если взглянуть на развитие двух данных платформ, выходит интересная картина. Первые версии Java EE были созданы при участии IBM. Они вышли крутыми, но неповоротливыми, тяжеловесными, неудобными в использовании. Разработчики плевались из-за необходимости поддерживать большое количество конфигурационных файлов и из-за прочих причин, усложняющих разработку.

В то же время на свет появился Spring IoC. Это была маленькая, красивая и приятная в обращении библиотека. В ней также использовался конфигурационный файл, но в отличии от Java EE, он был один. Простота Spring привела к тому, что практически все стали использовать данный фреймворк в своих проектах.

А далее Spring и Java EE начали свой путь к одному и тому же, но с разных концов. Компания Pivotal Software, разработчик Spring, стали выпускать проект за проектом, чтобы покрыть все возможные и невозможные потребности Java-разработчиков. Постепенно то, что раньше называлось Spring, сначала стало одним из проектов, а потом и вовсе слилось с несколькими другими проектами в Spring Core. Все это привело к неминуемому усложнению Spring по сравнению с тем, каким он был изначально. Со временем следить за всем клубком зависимостей спринга стало уж совсем сложно, и возникла потребность в отдельной библиотеке, которая стала бы загружать и запускать все сама (сейчас где-то икнул так горячо любимый Spring Boot).

Все это время JCP работал над одним — добиться максимального упрощения всего, что только можно внутри Java EE. В итоге в современном EJB для описания бина достаточно указать одну аннотацию над классом, что предоставляет разработчику доступ ко всей мощи технологии Enterprise Java Beans. И подобные упрощения затронули каждую спецификацию внутри Java EE.

В итоге по функционалу Spring и Java EE примерно разделяют паритет. Где-то что-то лучше, где-то что-то хуже, но если смотреть глобально, больших различий нет. То же самое касается сложности работы. И Spring, и Java EE являются превосходными инструментами. Пожалуй, лучшими из того, что сейчас есть, для построения корпоративных сетевых приложений на языке Java.

!! Однако, Java EE может работать в общем случае только в рамках Enterprise Application Server’a (Tomcat таковым не является), а приложение на Spring стеке может работать на чем угодно (на том же Tomcat), и даже вообще без сервера (так как запустит его внутри себя самостоятельно).

!! Это делает Spring идеальным инструментом для разработки небольших приложений с GUI на Front-end или для микросервисной архитектуры. Но отказ от зависимости от серверов приложений отрицательно сказался на масштабируемости Spring-приложений.

А Java EE хорошо подходит для реализации масштабируемого монолитного кластерного приложения.

Пример Web profile: Tomcat

Пример Full profile: Glassfish

Основные концепции
Приложения строятся из компонентов, работающих под управлением контейнеров.
Используются следующие принципы:
Inversion of Control (IoC) + Contexts & Dependency Injection (CDI).
Location Transparency.
https://javarush.ru/groups/posts/2637-vvedenie-v-java-ee - классное объяснение

https://ru.photo-555.com/2403908-java-ee-interview-questions - вопросы с собеса

## События в EJB

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

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

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