Skip to content

Commit cb5d218

Browse files
committed
Spring: updated task and conspect
1 parent 7f9b494 commit cb5d218

File tree

3 files changed

+500
-1
lines changed

3 files changed

+500
-1
lines changed
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
% !TEX TS-program = xelatex
2+
% !TEX encoding = UTF-8 Unicode
3+
\documentclass[a4paper,12pt]{article}
4+
5+
% Поддержка Unicode и шрифтов для кроссплатформенности
6+
\usepackage{fontspec}
7+
\usepackage{polyglossia}
8+
9+
% Основные шрифты (кроссплатформенные)
10+
\setmainfont{DejaVu Serif}
11+
\setsansfont{DejaVu Sans}
12+
\setmonofont{DejaVu Sans Mono}
13+
14+
% Для polyglossia кириллица
15+
\newfontfamily\cyrillicfont{DejaVu Serif}
16+
\newfontfamily\cyrillicfontsf{DejaVu Sans}
17+
\newfontfamily\cyrillicfonttt{DejaVu Sans Mono}
18+
19+
20+
% Настройки русского языка
21+
\setdefaultlanguage{russian}
22+
\setotherlanguages{english}
23+
\defaultfontfeatures{Ligatures=TeX}
24+
25+
% Геометрия страницы
26+
\usepackage[a4paper, margin=2cm]{geometry}
27+
28+
% Цвета для подсветки кода
29+
\usepackage{xcolor}
30+
\definecolor{codegreen}{rgb}{0,0.6,0}
31+
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
32+
\definecolor{codepurple}{rgb}{0.58,0,0.82}
33+
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
34+
35+
% Подсветка синтаксиса для Java
36+
\usepackage{listings}
37+
\lstdefinestyle{java}{
38+
backgroundcolor=\color{backcolour},
39+
commentstyle=\color{codegreen},
40+
keywordstyle=\color{magenta},
41+
numberstyle=\tiny\color{codegray},
42+
stringstyle=\color{codepurple},
43+
basicstyle=\ttfamily\footnotesize,
44+
breakatwhitespace=false,
45+
breaklines=true,
46+
captionpos=b,
47+
keepspaces=true,
48+
numbers=left,
49+
numbersep=5pt,
50+
showspaces=false,
51+
showstringspaces=false,
52+
showtabs=false,
53+
tabsize=2,
54+
frame=single,
55+
framesep=3pt,
56+
rulecolor=\color{gray},
57+
xleftmargin=10pt,
58+
framexleftmargin=10pt,
59+
framexrightmargin=5pt,
60+
framextopmargin=2pt,
61+
framexbottommargin=2pt
62+
}
63+
64+
\lstset{style=java}
65+
66+
% Заголовки разделов
67+
\usepackage{titlesec}
68+
\titleformat{\section}{\normalfont\Large\bfseries}{\thesection}{1em}{}
69+
\titleformat{\subsection}{\normalfont\large\bfseries}{\thesubsection}{1em}{}
70+
71+
% Интервалы
72+
\usepackage{setspace}
73+
\onehalfspacing
74+
75+
% Гиперссылки
76+
\usepackage{hyperref}
77+
\hypersetup{
78+
colorlinks=true,
79+
linkcolor=blue,
80+
filecolor=magenta,
81+
urlcolor=cyan,
82+
}
83+
84+
% Названия разделов на русском
85+
\addto\captionsrussian{\renewcommand{\contentsname}{Содержание}}
86+
\addto\captionsrussian{\renewcommand{\listfigurename}{Список рисунков}}
87+
\addto\captionsrussian{\renewcommand{\listtablename}{Список таблиц}}
88+
89+
% Метаданные документа
90+
\title{Современная разработка на Spring Boot: REST API с валидацией и базой данных}
91+
\author{Конспект по разработке веб-приложений}
92+
\date{\today}
93+
94+
\begin{document}
95+
96+
\maketitle
97+
98+
\tableofcontents
99+
100+
\section{Введение}
101+
Данный конспект посвящен созданию RESTful API с использованием современного стека технологий Spring Boot. Рассматриваются ключевые компоненты для быстрой разработки веб-приложений с поддержкой базы данных, валидации данных и автоматического конфигурирования.
102+
103+
\subsection{Технологический стек}
104+
\begin{enumerate}
105+
\item \textbf{Spring WEB} --- основной модуль для создания веб-приложений и REST API
106+
\item \textbf{H2 Database} --- in-memory база данных для разработки и тестирования
107+
\item \textbf{Spring Boot DevTools} --- инструменты для ускорения разработки (автоматическая перезагрузка)
108+
\item \textbf{Spring Data JPA} --- абстракция для работы с базами данных через JPA
109+
\item \textbf{Lombok} --- библиотека для автоматической генерации шаблонного кода
110+
\item \textbf{Validation} --- валидация входных данных с помощью Jakarta Validation
111+
\item \textbf{Java 17/21} --- современные LTS-версии Java с улучшенными возможностями
112+
\end{enumerate}
113+
114+
\section{Модель данных}
115+
Создание сущности для работы с заметками. Используется аннотации JPA для маппинга на таблицу базы данных.
116+
117+
\subsection{Сущность Note}
118+
\begin{lstlisting}[language=Java,caption=Модель данных: класс Note]
119+
package com.example.demo.model;
120+
121+
import jakarta.persistence.*;
122+
import lombok.*;
123+
124+
@Entity
125+
@Table(name = "notes")
126+
@Getter
127+
@Setter
128+
@NoArgsConstructor
129+
@AllArgsConstructor
130+
@Builder
131+
@ToString
132+
@EqualsAndHashCode
133+
public class Note {
134+
135+
@Id
136+
@GeneratedValue(strategy = GenerationType.IDENTITY)
137+
private Long id;
138+
139+
@Column(nullable = false,length = 100)
140+
private String title;
141+
142+
@Column(nullable = false, columnDefinition = "TEXT")
143+
private String content;
144+
}
145+
\end{lstlisting}
146+
147+
\textbf{Пояснения к аннотациям:}
148+
\begin{enumerate}
149+
\item \texttt{@Entity} --- помечает класс как JPA-сущность
150+
\item \texttt{@Table(name = "notes")} --- указывает имя таблицы в базе данных
151+
\item \texttt{@Id} и \texttt{@GeneratedValue} --- определяют первичный ключ и стратегию генерации
152+
\item \texttt{@Column} --- настраивает параметры колонки (обязательность, размер, тип)
153+
\item \texttt{@Getter}, \texttt{@Setter} --- генерируют геттеры и сеттеры (Lombok)
154+
\item \texttt{@NoArgsConstructor}, \texttt{@AllArgsConstructor} --- генерируют конструкторы без параметров и со всеми параметрами
155+
\item \texttt{@Builder} --- создает паттерн Builder для удобного создания объектов
156+
\item \texttt{@ToString}, \texttt{@EqualsAndHashCode} --- генерируют методы toString(), equals() и hashCode()
157+
\end{enumerate}
158+
159+
\section{Репозиторий данных}
160+
Spring Data JPA предоставляет готовые CRUD-операции через наследование от JpaRepository.
161+
162+
\subsection{NoteRepository}
163+
\begin{lstlisting}[language=Java,caption=Репозиторий для работы с заметками]
164+
package com.example.demo.repositories;
165+
166+
import com.example.demo.model.Note;
167+
import org.springframework.data.jpa.repository.JpaRepository;
168+
import org.springframework.stereotype.Repository;
169+
170+
@Repository
171+
public interface NoteRepository extends JpaRepository<Note, Long> {
172+
}
173+
\end{lstlisting}
174+
175+
\textbf{Важное замечание:} Spring Boot автоматически сканирует все классы внутри пакета (и подпакетов) на предмет аннотаций, включая \texttt{@Repository}. Обнаруженные компоненты регистрируются в ApplicationContext, после чего происходит автоматическая инъекция зависимостей (DI).
176+
177+
\section{DTO и валидация}
178+
Для передачи данных между клиентом и сервером используются DTO (Data Transfer Objects) с валидацией.
179+
180+
\subsection{NoteCreateDto с валидацией}
181+
\begin{lstlisting}[language=Java,caption=DTO для создания заметки с валидацией]
182+
record NoteCreateDto(
183+
@NotEmpty
184+
@Size(max = 100,
185+
message = "Слишком длинная строка")
186+
String title,
187+
188+
@Size(max = 10000,
189+
message = "Слишком длинная строка")
190+
String content
191+
) {
192+
193+
}
194+
\end{lstlisting}
195+
196+
\textbf{Аннотации валидации:}
197+
\begin{enumerate}
198+
\item \texttt{@NotNull} --- поле не должно быть null (для объектов)
199+
\item \texttt{@NotEmpty} --- поле не null и не пустая коллекция/строка
200+
\item \texttt{@NotBlank} --- не null, не пустая и не состоит только из пробелов (лучше всего для строк)
201+
\item \texttt{@Size(min=, max=)} --- ограничение на размер строки или коллекции
202+
\item \texttt{@Min/@Max} --- ограничение для числовых значений
203+
\item \texttt{@Positive/@PositiveOrZero} --- положительные числа
204+
\item \texttt{@Past/@Future} --- проверка дат
205+
\item \texttt{@Email} --- базовая проверка email-адреса
206+
\item \texttt{@Pattern(regexp = "...")} --- проверка по регулярному выражению
207+
\item \texttt{@AssertTrue/@AssertFalse} --- кастомная логическая валидация
208+
\end{enumerate}
209+
210+
\section{Контроллер REST API}
211+
Реализация CRUD-операций для управления заметками.
212+
213+
\subsection{NoteController}
214+
\begin{lstlisting}[language=Java,caption=REST контроллер для работы с заметками]
215+
package com.example.demo.controllers;
216+
217+
import com.example.demo.model.Note;
218+
import com.example.demo.repositories.NoteRepository;
219+
import jakarta.validation.Valid;
220+
import lombok.RequiredArgsConstructor;
221+
import org.springframework.http.HttpStatus;
222+
import org.springframework.http.ResponseEntity;
223+
import org.springframework.web.bind.annotation.*;
224+
225+
import java.util.List;
226+
import java.util.concurrent.atomic.AtomicReference;
227+
228+
@RestController
229+
@RequestMapping("/api")
230+
@RequiredArgsConstructor
231+
public class NoteController {
232+
233+
private final NoteRepository noteRepository;
234+
235+
@GetMapping
236+
public List<Note> getAllNotes() {
237+
return noteRepository.findAll();
238+
}
239+
240+
//ResponseEntity для корректных статусов
241+
@PostMapping
242+
public ResponseEntity<Note> createNote(@RequestBody @Valid NoteCreateDto noteDto) {
243+
var note = Note.builder().title(noteDto.title()).content(noteDto.content()).build();
244+
var saved = noteRepository.save(note);
245+
return new ResponseEntity(saved,HttpStatus.CREATED);
246+
}
247+
248+
@PutMapping("/{id}")
249+
public ResponseEntity<Note> updateNote(
250+
@PathVariable Long id, // или Long, если ещё не перешёл на UUID
251+
@RequestBody @Valid NoteCreateDto dto) { // @Valid — обязательно для валидации
252+
253+
// Возвращаем готовый ResponseEntity сразу через orElseThrow + map
254+
return noteRepository.findById(id)
255+
.map(existingNote -> {
256+
existingNote.setTitle(dto.title());
257+
existingNote.setContent(dto.content());
258+
Note updatedNote = noteRepository.save(existingNote);
259+
return ResponseEntity.ok(updatedNote); // 200 OK
260+
})
261+
.orElseGet(() -> ResponseEntity.notFound().build()); // 404 Not Found
262+
}
263+
264+
@DeleteMapping("/{id}")
265+
public ResponseEntity<Void> deleteNote(@PathVariable Long id) {
266+
noteRepository.deleteById(id);
267+
return ResponseEntity.noContent().build();
268+
}
269+
}
270+
\end{lstlisting}
271+
272+
\textbf{Ключевые особенности:}
273+
\begin{enumerate}
274+
\item \texttt{@RestController} --- комбинирует @Controller и @ResponseBody
275+
\item \texttt{@RequiredArgsConstructor} --- генерирует конструктор для final-полей (Lombok)
276+
\item \texttt{ResponseEntity} --- позволяет контролировать HTTP-статусы и заголовки
277+
\item \texttt{@Valid} --- активирует валидацию DTO перед обработкой
278+
\item Функциональный подход с \texttt{map()} и \texttt{orElseGet()} для обработки Optional
279+
\item Корректные HTTP-статусы: 201 Created, 200 OK, 404 Not Found, 204 No Content
280+
\end{enumerate}
281+
282+
\section{Глобальная обработка ошибок}
283+
Обработка исключений валидации на уровне приложения.
284+
285+
\subsection{GlobalExceptionHandler}
286+
\begin{lstlisting}[language=Java,caption=Глобальный обработчик исключений]
287+
package com.example.demo.controllers;
288+
289+
import org.springframework.http.ResponseEntity;
290+
import org.springframework.web.bind.MethodArgumentNotValidException;
291+
import org.springframework.web.bind.annotation.ExceptionHandler;
292+
import org.springframework.web.bind.annotation.RestControllerAdvice;
293+
294+
import java.util.HashMap;
295+
import java.util.Map;
296+
297+
@RestControllerAdvice
298+
public class GlobalExceptionHandler {
299+
300+
@ExceptionHandler(MethodArgumentNotValidException.class)
301+
public ResponseEntity<Map<String, String>> handleValidationExceptions(
302+
MethodArgumentNotValidException ex) {
303+
Map<String, String> errors = new HashMap<>();
304+
ex.getBindingResult().getFieldErrors().forEach(error ->
305+
errors.put(error.getField(), error.getDefaultMessage()));
306+
307+
return ResponseEntity.badRequest().body(errors);
308+
}
309+
}
310+
\end{lstlisting}
311+
312+
\textbf{Принцип работы:}
313+
\begin{enumerate}
314+
\item \texttt{@RestControllerAdvice} --- применяет обработчики ко всем контроллерам
315+
\item \texttt{@ExceptionHandler} --- перехватывает конкретные типы исключений
316+
\item \texttt{MethodArgumentNotValidException} --- генерируется при провале валидации
317+
\item Формируется понятный JSON-ответ с ошибками для каждого поля
318+
\item Возвращается HTTP-статус 400 Bad Request
319+
\end{enumerate}
320+
321+
\section{Рекомендации по разработке}
322+
\begin{enumerate}
323+
\item \textbf{Валидация} --- всегда используйте \texttt{@Valid} для DTO в контроллерах
324+
\item \textbf{HTTP-статусы} --- возвращайте соответствующие статусы для каждой операции
325+
\item \textbf{DTO} --- никогда не передавайте сущности напрямую в клиент, используйте DTO
326+
\item \textbf{Иммутабельность} --- используйте record для DTO вместо классов
327+
\item \textbf{Обработка ошибок} --- централизованная обработка исключений улучшает поддерживаемость
328+
\item \textbf{Производительность} --- для продакшена замените H2 на PostgreSQL или MySQL
329+
\end{enumerate}
330+
331+
\section{Заключение}
332+
Представленный стек технологий позволяет быстро создавать надежные REST API с минимальным количеством шаблонного кода. Использование Lombok, Spring Data JPA и валидации значительно ускоряет разработку, а правильная обработка ошибок и HTTP-статусов делает API профессиональным и удобным для клиентов.
333+
334+
Данный подход легко масштабируется и может быть дополнен аутентификацией, авторизацией, кэшированием и другими enterprise-функциями при необходимости.
335+
336+
\end{document}

0 commit comments

Comments
 (0)