Создание Spring Boot Data Rest CRUD-приложения

Создадим crud приложение, только теперь с использованием Spring Data Rest.

Создадим новое Spring Boot приложение с такими папками и файлами.

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

Нет дао класса, сервис класса и даже контроллера. А если вы пролистаете данный урок далее, то увидите, что в файлах вообще практически нет кода.

Search Icon

Но при всем этом, это полностью рабочее crud приложение. Что? Как такое возможно?

Давайте же разберемся.

Для начала, давайте добавим зависимость для поддержки Spring Data Rest.

4.0.0 org.springframework.boot spring-boot-starter-parent 3.1.5 com.SpringBootApps firstSpringBootDataRestCRUDApp 0.0.1-SNAPSHOT firstSpringBootDataRestCRUDApp Demo project for Spring Boot 17 org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web com.mysql mysql-connector-j runtime org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-devtools test org.springframework.boot spring-boot-starter-data-rest org.springframework.boot spring-boot-maven-plugin

В прошлом уроке мы задавали вопрос о DAO имплементациях. Нужно ли их так много?

Но тот же вопрос можно применить и к контроллерам! Нужно ли для каждой сущности писать маппинги(ну там GetMapping, PostMapping и т.д.) для CRUD операций?

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

Search Icon

Spring может сам создать эти методы за кулисами!

Всё что нам нужно, это создать интерфейсы расширяющие JpaRepository для сущностей, а спринг сам предоставит нам адреса, которые мы писали в GetMapping, PostMapping и т.д. по которым мы можем совершать CRUD операции. Адреса эти формируются автоматически по имени класса, который мы передали в JpaRepository<[По имени этого класса],Integer>.

Например, для JpaRepository<Actor, Integer> Spring Data Rest сгенерирует адреса /actors, /actors/{actorId} и т.д. для разных HTTP методов.

Также важно упомянуть что в JSON ответах от таких сгенерированных REST методов можно увидеть некоторые метаданные. Например, по какой ссылке был сделан запрос или количество переданных объектов и т.д.

package com.SpringBootApps.firstSpringBootDataRestCRUDApp.dao; import org.springframework.data.jpa.repository.JpaRepository; //Как уже было сказано адреса формируются автоматически по имени класса, //который мы передали в JpaRepository<[По имени этого класса],Integer>. public interface ActorRepository extends JpaRepository { }

Давайте же протестируем созданные обработчики.

В таблице actor сейчас три актера:

Давайте выберем из БД всех актеров GET запросом с помощью автоматически сгенерированного с помощью Spring Data Rest адреса /actors.

Как видим, все актеры успешно были получены.

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

Также на скриншоте снизу можно увидеть метаданные о страницах – количество актеров на странице (три), номер страницы (нулевая страница), размер страницы (на странице может быть всего 20 актеров). То есть актеры разбиваются на страницы. Пока сильно не будем углубляться, что такое страницы и как с ними взаимодействовать.

Давайте теперь выберем из БД одного конкретного актера GET запросом с помощью автоматически сгенерированного с помощью Spring Data Rest адреса /actors/{actorId}.

Как видим, актер с id два был успешно выбран из БД и прислан в ответ на GET запрос. Также с метаданными.

Давайте теперь добавим в БД нового актера POST запросом с помощью автоматически сгенерированного с помощью Spring Data Rest адреса /actors. Для этого пишем в body данные в формате JSON, которые мы хотим добавить в БД.

Выше видим, что в результате выполнения POST запроса был получен код успешного выполнения операции201. Ниже можно увидеть, что актер успешно добавился в БД.

Давайте теперь обновим в БД актера PUT запросом с помощью автоматически сгенерированного с помощью Spring Data Rest адреса /actors/{actorId}. Для этого пишем в body данные в формате JSON, которыми мы хотим обновить актера с id, который указывается в конце адреса.

Выше видим, что в результате выполнения PUT запроса был получен код успешного выполнения операции 201. Ниже можно увидеть, что актер с id четыре успешно обновился в БД.

Давайте теперь удалим из БД актера DELETE запросом с помощью автоматически сгенерированного с помощью Spring Data Rest адреса /actors/{actorId}. Для этого пишем в конце адреса id актера, которого мы хотим удалить.

Выше видим, что в результате выполнения DELETE запроса был получен код успешного выполнения операции201. Ниже можно увидеть, что актер с id четыре успешно удалился из БД.

Search Icon

Еще раз заметим. Все эти ссылки были фактически ПОДАРЕНЫ нам средствами Spring Data Rest. Это может серьезно сэкономить время если нам нужны простейшие crud операции.


Доп. конфигурация Spring Boot Data Rest приложения

А что если нам нужно чтобы Spring Data Rest не генерировал автоматически некоторые адреса для CRUD?

Что если мы хотим написать их код вручную в контроллере (например, для POST и DELETE)? То есть нам не нужны простейшие POST и DELETE операции по адресу /actors, мы хотим написать чуть более сложные обработчики для этого адреса вручную в контроллере.

Для этого можно просто отключить генерацию адресов для POST и DELETE в классе, который реализует RepositoryRestConfigurer переопределяя метод configureRepositoryRestConfiguration.

package com.SpringBootApps.firstSpringBootDataCRUDApp.config; import org.springframework.context.annotation.Configuration; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer; import org.springframework.http.HttpMethod; @Configuration public class MyDataRestConfig implements RepositoryRestConfigurer { @Override public void configureRepositoryRestConfiguration( RepositoryRestConfiguration config, CorsRegistry cors) { //здесь в массив передаем не нужные для генерации HTTP методы HttpMethod[] theUnsupportedActions={HttpMethod.POST, HttpMethod.DELETE}; config.getExposureConfiguration() //Ниже пишем класс, который мы передавали //в JpaRepository на основе //которого генерировались методы для CRUD. .forDomainType(Actor.class) //Передаем в методы ниже созданный массив. .withItemExposure((metadata, httpMethods) -> httpMethods.disable(theUnsupportedActions)) .withCollectionExposure((metadata, httpMethods) -> httpMethods.disable(theUnsupportedActions)); //Все. Автоматическая генерация адресов для совершения //Post и Delete запросов над сущностью actor отключена. } }

Что такое Docker и зачем он нужен?

Docker — инструмент для контейнеризации. Узнайте, как создавать, запускать и управлять приложениями в изолированных Docker-образах без лишних зависимостей.
Time to read: 13

Docker Hub: назначение и использование

Как работать с Docker Hub: загрузка образов, репозитории, теги версий. Примеры команд для скачивания и запуска контейнеров из облачного хранилища.
Time to read: 17

Сборка Java приложения в Docker

Упакуйте Spring Boot приложение в Docker: создание Dockerfile, настройка зависимостей, сборка образа и загрузка на Docker Hub. Запуск контейнеров.
Time to read: 20