Даний матеріал присвячений Spring REST. Спробуємо розібратись на практичному завданні, що це таке, та як правильно писати RESTful веб додатки на Spring.
Ми вже з вами знаємо що таке REST з попередніх матеріалів. Ми також розуміємо як працює веб. Звісно, якщо ви ще цього не знаєте, то перш ніж продовжити прочитання даного матеріалу, я раджу ознайомитись з основами.
Створюємо RESTful додаток на Spring Boot
Зараз ви побачите – наскільки просто і швидко зробити REST API на Spring Boot. Фреймворк робить всю чорнову роботу за програміста та залишає можливість просто зосередити зусилля на вирішенні бізнес-проблеми.
Для початку нам потрібен простий проєкт Spring Boot. Переходимо на сайт https://start.spring.io/ і обираємо залежність для Web. Не забуваймо обрати потрібний нам збірник (Maven, Gradle), версію Java, вказати назву проєкту і тд:

Spring Boot Controller
Перш ніж почати писати код, потрібно ознайомитись з термінологією. Якщо ви писали джава додатки на Servlet API, то памʼятаєте, що за приймання вхідних запитів від юзерів відповідає Java Servlet. В Spring таким аналогом є Controller. Тільки на відміну від сервлетів, контролер набагато зручніший у використанні і написанні. Оскільки в Controller кожен метод з відповідною анотацією відповідає тільки за 1 тип запиту.
Для того, щоб Java клас став контролером, достатньо навішати на нього анотацію @Controller. Але якщо ми працюємо з REST, то навідміну від Spring MVC нам слід використати анотацію @RestController. Так ми вкажемо Spring, що даний клас є рест контролером. За замовчуванням такий клас приймає і повертає дані у форматі JSON, що є стандартним форматом роботи з REST.
Далі, ми починаємо писати методи нашого класу (з відповідними анотаціями) для обробки вхідних запитів. Для повернення ресурсу нам підійде GET; для створення – POST; DELETE для видалення; PUT для оновлення ресурсу.
Назви ендпоінтів (урл посилання) слід давати згідно з REST конвенціями. Більш детальніше можна ознайомитись з ними в матеріалі Основи REST.
Реалізація REST контролера
Для спрощеної демонстрації коду, я не буду використовувати щось занадто складне (накшталт баз даних) для зберігання інформації. Уявимо що нам доручили написати API книжкового магазину. Нам треба реалізувати додавання нової книги, повернення всіх книг, пошук за назвою, отримання за ідентифікатором, оновлення інформації про книгу, видалення книги. Зберігатимемо ми все в звичайному Java List.
Перш за все, створимо клас книги. Для цього я скористаюсь Java Record щоб не генерувати getter, setter, equals, hashCode.
package com.antitutor.model; public record BookModel(Integer id, String title, String author) { }
Далі справа за контролером:
package com.antitutor.controller; import com.antitutor.model.BookModel; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; @RestController @RequestMapping("/api/books") public class BookController { private static List<BookModel> books = new ArrayList<>(); @GetMapping public List<BookModel> findAll() { return books; } @GetMapping("/{id}") public BookModel getById(@PathVariable Integer id) { return books.stream() .filter(it -> it.id().equals(id)) .findFirst() .orElse(null); } @GetMapping("/search") public List<BookModel> search(@RequestParam String title) { return books.stream() .filter(it -> it.title().equalsIgnoreCase(title)) .toList(); } @PostMapping public ResponseEntity<Void> create(@RequestBody BookModel book) { books.add(book); return ResponseEntity.status(HttpStatus.CREATED) .build(); } @PutMapping public ResponseEntity<Void> edit(@RequestBody BookModel book) { books.stream().filter(it -> it.id().equals(book.id())) .findFirst() .ifPresent(bookToDelete -> books.remove(bookToDelete)); books.add(book); return ResponseEntity.status(HttpStatus.ACCEPTED) .build(); } @DeleteMapping("/{id}") public ResponseEntity<Void> delete(@PathVariable Integer id) { books.stream().filter(it -> it.id().equals(id)) .findFirst() .ifPresent(bookToDelete -> books.remove(bookToDelete)); return ResponseEntity.status(HttpStatus.OK) .build(); } }
Як видно з прикладу вище, код дуже схожий на той, що ми вже писали в Spring MVC Thymeleaf додатку. Відмінність полягає в тому, що тепер контролер оперує не сторінками html, а JSON. Тепер будь який клієнт хоч то звичайний сайт на HTML, CSS, JavaScript, мобільний додаток, інший сервер, можуть викликати наш REST API і працювати з книгами.
Як протестувати REST API
Для тестування наших ендпоінтів (саме так називаються методи в контролері), не обов’язково писати JavaScript код, щоб викликати методи контролера. Для цих цілей є спеціальні додатки. Один з таких – Postman.
Його встановлення і функціонал будуть зрозумілі навіть не досвідченим девелоперам. Але я все ж зроблю декілька сріншотів з мого процесу тестування:

Після створення книги, ми можемо спробувати дістати всі, щоб переконатись в правильності роботи додатку:

Відповідним чином слід тестувати інші методи контролера.
Це все, що стосується Spring REST. Як бачите, писати RESTful додатки не так вже й складно. Достатньо скористатись декількома анотаціями. Розробники фреймворку Spring зробили все, щоб ви сфокусувались на вирішенні бізнес потреб, замість складних налаштувань.
На нашому каналі є також декілька відео присвячених REST. Ось одне з них:
Приємного перегляду!
Залишити відповідь