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

Раздел: Spring Boot

Раздел посвящён Spring Boot — инструменту для быстрой и простой разработки Spring-приложений с минимальной настройкой.

Все разделы
Иконка Spring Boot

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

Last updated: 12 мая 2025 г.

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

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

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

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

Search Icon

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

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

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

1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0"
3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
5         https://maven.apache.org/xsd/maven-4.0.0.xsd">
6    <modelVersion>4.0.0</modelVersion>
7    <parent>
8        <groupId>org.springframework.boot</groupId>
9        <artifactId>spring-boot-starter-parent</artifactId>
10        <version>3.1.5</version>
11        <relativePath/> <!-- lookup parent from repository -->
12    </parent>
13    <groupId>com.SpringBootApps</groupId>
14    <artifactId>firstSpringBootDataRestCRUDApp</artifactId>
15    <version>0.0.1-SNAPSHOT</version>
16    <name>firstSpringBootDataRestCRUDApp</name>
17    <description>Demo project for Spring Boot</description>
18    <properties>
19        <java.version>17</java.version>
20    </properties>
21    <dependencies>
22        <dependency>
23            <groupId>org.springframework.boot</groupId>
24            <artifactId>
25                spring-boot-starter-data-jpa
26            </artifactId>
27        </dependency>
28        <dependency>
29            <groupId>org.springframework.boot</groupId>
30            <artifactId>spring-boot-starter-web</artifactId>
31        </dependency>
32        <dependency>
33            <groupId>com.mysql</groupId>
34            <artifactId>mysql-connector-j</artifactId>
35            <scope>runtime</scope>
36        </dependency>
37        <dependency>
38            <groupId>org.springframework.boot</groupId>
39            <artifactId>spring-boot-starter-test</artifactId>
40            <scope>test</scope>
41        </dependency>
42        <dependency>
43            <groupId>org.springframework.boot</groupId>
44            <artifactId>spring-boot-devtools</artifactId>
45            <scope>test</scope>
46        </dependency>
47        <!--Добавим зависимость для поддержки Spring Data Rest-->
48        <dependency>
49            <groupId>org.springframework.boot</groupId>
50            <artifactId>spring-boot-starter-data-rest</artifactId>
51        </dependency>
52    </dependencies>
53
54    <build>
55        <plugins>
56            <plugin>
57                <groupId>org.springframework.boot</groupId>
58                <artifactId>
59                    spring-boot-maven-plugin
60                </artifactId>
61            </plugin>
62        </plugins>
63    </build>
64
65</project>

В прошлом уроке мы задавали вопрос о 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 методов можно увидеть некоторые метаданные. Например, по какой ссылке был сделан запрос или количество переданных объектов и т.д.

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

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

В таблице 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.

1package com.SpringBootApps.firstSpringBootDataCRUDApp.config;
2
3import org.springframework.context.annotation.Configuration;
4import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
5import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
6import org.springframework.http.HttpMethod;
7
8@Configuration
9public class MyDataRestConfig implements RepositoryRestConfigurer {
10
11    @Override
12    public void configureRepositoryRestConfiguration(
13            RepositoryRestConfiguration config, CorsRegistry cors) {
14
15        //здесь в массив передаем не нужные для генерации HTTP методы
16        HttpMethod[] theUnsupportedActions={HttpMethod.POST, HttpMethod.DELETE};
17
18        config.getExposureConfiguration()
19                //Ниже пишем класс, который мы передавали
20                //в JpaRepository<Actor, Integer> на основе
21                //которого генерировались методы для CRUD.
22                .forDomainType(Actor.class)
23                //Передаем в методы ниже созданный массив.
24                .withItemExposure((metadata, httpMethods) ->
25                        httpMethods.disable(theUnsupportedActions))
26                .withCollectionExposure((metadata, httpMethods) ->
27                        httpMethods.disable(theUnsupportedActions));
28
29        //Все. Автоматическая генерация адресов для совершения
30        //Post и Delete запросов над сущностью actor отключена.
31
32    }
33}

Дополнительные материалы

Additional Material Icon

Следующие уроки

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

13
мин.

Similar Articles Icon
Divider

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

17
мин.

Similar Articles Icon
Divider

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

20
мин.

Similar Articles Icon