Курс "Объектно-ориентированное программирование"
  • Главная
  • 1 семестр (осень 2021)
    • Видео
    • Конспект лекций
      • Лекция 1
      • Лекция 2
      • Лекция 3
      • Лекция 4
      • Лекция 5
      • Лекция 6
      • Лекция 7
      • Лекция 8
      • Лекция 9
      • Лекция 10
      • Лекция 11
      • Лекция 12
      • Лекция 13
      • Лекция 14
      • Лекция 15
    • Лабораторные работы
      • Лабораторная работа 1
        • 1. Установка программного обеспечения, создание и запуск проекта
        • 2. Основы синатксиса Java
        • Задание на лабораторную работу
      • Лабораторная работа 2
        • Синтаксис создания классов
        • Задание на лабораторную работу
      • Лабораторная работа 3
        • Инкапсуляция
        • Язык моделирования UML
        • Задание на лабораторную работу
      • Лабораторная работа 4
        • Наследование и композиция
        • Наследование и композиция в UML
        • Задание на лабораторную работу
      • Лабораторная работа 5
        • Задание на лабораторную работу
      • Лабораторная работа 6
        • Абстрактные классы и интерфейсы в UML
        • Задание на лабораторную работу
  • 2 семестр (весна 2022)
    • Конспект лекций
      • Лекция 1-2
      • Лекция 3-4
      • Лекция 5
      • Лекция 6
      • Лекция 7-8
      • Лекция 9
      • Лекция 10
      • Лекция 11-12
      • Лекция 13-14
      • Лекция 15
  • Архив
    • Лекция 2
    • Архив
      • Заметки по абстракции
      • Конспект лекций
        • 1. Принцип Separation of Concerns, контроллер и представление
        • 2. Паттерн MVC
        • 3. Клиент-серверная архитектура. Создание простой RESTful веб-службы с помощью Spring Boot.
        • 4. Внедрение зависимостей (Dependency Injection)
        • 5. Интеграция приложения с СУБД
        • 6. Фреймворк Spring MVC
        • 7. Работа со Spring Security, часть 1
        • 8. Работа со Spring Security, часть 2
        • 9. Развертывание приложения в Heroku
      • Заочники (осень 2022)
      • Архив
        • Лекции
          • Draft
            • 5. Абстрактные классы и интерфейсы. Механизм обратного вызова
            • 6. Анонимные классы
          • Блок лекций 1
            • Дополнительные задания и литература
            • 1. Базовые сведения об ООП
            • 1. Обобщенные типы. Автоупаковка и автораспаковка.
            • 2. Знакомство с языком Java
          • Блок лекций 2
            • 5. Абстрактные классы и интерфейсы. Механизм обратного вызова.
            • 6. Анонимные объекты, классы, методы. Лямбда-выражения.
            • 7. Аргументы переменной длины. Принцип абстракции. Дополнительные принципы ООП.
          • Блок лекций 3
            • 2. Коллекции объектов.
            • 3. Паттерн Итератор. Компараторы. Потоки в Java (Streams API)
          • Блок лекций 4
            • 1. Исключения в Java. Обработка исключений.
          • Блок лекций 5
            • Статические поля и методы
            • Вложенные и внутренние классы
            • Перечисления
          • Блок лекций 6
            • 2. Интеграция приложения с СУБД
        • Лабораторные работы
          • 2. Основы синтаксиса
            • Python
            • C#
          • Лабораторная работа 3
            • 1. Инкапсуляция
            • 2. Перегрузка методов
            • Задание на лабораторную работу
            • Теоретические вопросы
          • Лабораторная работа 4
            • Задание на лабораторную работу
            • Теоретические вопросы
          • Лабораторная работа 6
            • Задание на лабораторную работу
            • Теоретические вопросы
          • Лабораторная работа 7
            • Задание на лабораторную работу
            • Теоретические вопросы
          • Лабораторная работа 8
          • Лабораторная работа 9
          • Лабораторная работа 10
            • Задание на лабораторную работу
          • Лабораторная работа 11
            • Задание на лабораторную работу
          • Лабораторная работа 12
            • Пример выполнения лабораторной работы
            • Задание на лабораторную работу
        • Практические работы
          • Практическая работа 1
          • Практическая работа 2
        • Материалы по Java Spring
          • 1. Клиент-серверная архитектура. Создание простой RESTful веб-службы с помощью Spring Boot.
          • 4. Работа со Spring MVC, часть 1
          • 5. Работа со Spring MVC, часть 2
      • Конспект лекций
        • 1. История развития языков программирования
        • 2. Базовые термины ООП
        • 3. Понятие класса и объекта
        • 4. Создание объектов. Конструктор.
        • 5. Основные принципы ООП. Инкапсуляция.
        • 6. Перегрузка методов
        • 7. Повторное использование кода. Композиция и наследование
        • 8. Полиморфизм
        • 9. Абстрактные классы и интерфейсы
        • 10. Анонимные классы, интерфейсы, методы. Лямбда-выражения
        • 11. Принцип абстракции. Дополнительные принципы ООП
        • 12. Обобщенные типы. Автоупаковка и автораспаковка
        • 13. Коллекции
        • 14. Паттерн "Итератор". Компараторы. Фреймворк Streams API.
        • 15. Исключения в Java. Обработка исключений
        • 16. Принципы разработки графического интерфейса. Фреймворк JavaFX
        • 17. События в JavaFX
        • 20. Перечисления
      • Лабораторные работы
        • Лабораторная работа 2
          • 1. Синтаксис создания классов
          • 2. Язык моделирования UML
          • Задание на лабораторную работу
          • Теоретические вопросы
        • Лабораторная работа 3
          • 1. Инкапсуляция
          • 2. Перегрузка методов
          • Задание на лабораторную работу
        • Лабораторная работа 4
          • Наследование и композиция
          • Наследование и композиция в диаграмме классов UML
          • Задание на лабораторную работу
        • Лабораторная работа 5
          • Задание на лабораторную работу
          • Теоретические вопросы
        • Лабораторная работа 6
          • Задание (старое)
          • Теоретические вопросы
        • Лабораторная работа 8
          • Задание на лабораторную работу
        • Лабораторная работа 9
          • Задание на лабораторную работу
      • Видеолекции
      • Видеолекции
Powered by GitBook
On this page
  • 1. Теоретические сведения
  • 2. Создание и настройка Spring Boot проекта
  • 3. Создание контроллера, переход между страницами
  • 4. Получение данных формы
  • 5. Вывод данных из БД

Was this helpful?

Export as PDF
  1. Архив
  2. Архив
  3. Архив
  4. Материалы по Java Spring

4. Работа со Spring MVC, часть 1

Previous1. Клиент-серверная архитектура. Создание простой RESTful веб-службы с помощью Spring Boot.Next5. Работа со Spring MVC, часть 2

Last updated 5 years ago

Was this helpful?

1. Теоретические сведения

Spring MVC – веб-фреймворк, призванный упростить разработку веб-приложений. Опираясь на шаблон модель–представление–контроллер (Model-View-Controller, MVC), фреймворк Spring MVC помогает строить веб-приложения, столь же гибкие и слабо связанные, как сам фреймворк Spring.

Схема работы фреймворка Spring MVC

Схема работы фреймворка выглядит следующим образом:

Краткое описание схемы работы Spring MVC звучит следующим образом:

  • вначале DispatcherServlet (диспетчер сервлетов) получает запрос, далее он смотрит свои настройки, чтобы понять какой контроллер использовать (на рисунке Handler Mapping);

  • после получения имени контроллера запрос передается на обработку в этот контроллер (на рисунке Controller). В контроллере происходит обработка запроса и обратно посылается ModelAndView (модель — сами данные; view (представление) — как эти данные отображать);

  • DispatcherServlet на основании полученного ModelAndView, должен определить, какое представление будет выводить данные. Для этого используется арбитр представлений (View Resolver), который на основании полученного логического имени представления возвращает ссылку на файл View;

  • в представление передаются данные (Model) и обратно, если необходимо, посылается ответ от представления.

Давайте рассмотрим этот процесс более подробно:

  1. Когда запрос покидает браузер, он несет в себе информацию о требовании пользователя. По крайней мере, запрос будет нести в себе запрошенный URL. Но он может также нести дополнительные данные, такие как информация из формы, заполненной пользователем;

  2. Первой остановкой на пути запроса является DispatcherServlet. Как и большинство веб-фреймворков на языке Java, фреймворк Spring MVC пропускает все входящие запросы через единственный сервлет входного контроллера. Входной контроллер (front controller) является типичным шаблоном проектирования веб-приложений, где единственный сервлет берет на себя ответственность за передачу всех запросов остальным компонентам приложения, выполняющим фактическую их обработку. В Spring MVC входным контроллером является DispatcherServlet;

  3. Задача контроллера DispatcherServlet состоит в том, чтобы передать запрос контроллеру Spring MVC. Контроллер – это компонент Spring, обрабатывающий запрос. Но приложение может иметь несколько контроллеров, и входному контроллеру DispatcherServlet требуется помощь, чтобы определить, какому контроллеру передать запрос. Поэтому контроллер DispatcherServlet консультируется c одним или несколькими механизмами отображения (Handler Mapping) и выясняет, какой контроллер будет обрабатывать тот или иной запрос. При принятии решения механизм отображения в первую очередь руководствуется адресом URL в запросе;

  4. Как только будет выбран соответствующий контроллер, DispatcherServlet отправляет запрос в путь к выбранному контроллеру. Достигнув контроллера, запрос отдаст часть своего груза (информацию, отправленную пользователем) и терпеливо будет ждать, пока контроллер обработает эту информацию. (На самом деле хорошо спроектированный контроллер сам почти не занимается обработкой информации, вместо этого он делегирует ответственность за обработку одному или нескольким служебным объектам);

  5. В результате работы контроллера часто появляется некоторая информация, которая должна быть передана назад пользователю и отображена в браузере. Эта информация называется моделью (Model). Но отправки обратно необработанной информации недостаточно, перед отправкой ее следует представить в удобном для пользователя формате, обычно в HTML. Для этого информация должна быть передана в одно из представлений (View), которыми обычно являются JSP-страницы;

  6. Последнее, что должен сделать контроллер, – упаковать вместе модель и имя представления для отображения результатов в браузере. Затем он отсылает запрос вместе с моделью и именем представления обратно входному контроллеру DispatcherServlet;

  7. Чтобы контроллер не оказался тесно связанным с каким-либо конкретным представлением, имя представления, возвращаемое входному контроллеру DispatcherServlet, не определяет JSP-страницу непосредственно. Фактически оно даже не предполагает, что представление вообще является страницей JSP. Оно является лишь логическим именем представления, используемым затем для поиска фактического представления. Чтобы отобразить логическое имя представления в ссылку на конкретную реализацию, входной контроллер DispatcherServlet обратится к арбитру представлений (view resolver);

  8. Теперь, когда контроллер DispatcherServlet определил, какое представление будет отображать результаты, работа запроса подошла к концу. Его конечная остановка – реализация представления (возможно, страница JSP), куда он доставит модель данных. На этом работа запроса заканчивается. На основе модели данных представление создаст отображение страницы, которое будет отправлено обратно клиенту с другим (не таким трудолюбивым) курьером – объектом ответа.

Рассмотренную выше схему работы фреймворка можно также представить следующей диаграммой

2. Создание и настройка Spring Boot проекта

Создадим новый Spring Boot проект, выберем следующие модули

В новом проекте обратите внимание на структуру папок. В папке resources\templates будут содержаться html-файлы с использованием шаблонизатора Thymeleaf.

Создадим файл index.html. Обратите внимание, что в теге html необходимо указать пространство имен th для подключения тегов Thymeleaf.

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" xmlns:th="http://www.thymeleaf.org">
    <title>Index page</title>
</head>
<body>
    <h1>Hello, world!</h1>
</body>
</html>

В проекте Spring Boot MVC страница index будет автоматически передана при переходе на URL "/". Запустим проект и зайдем в браузер.

3. Создание контроллера, переход между страницами

Создадим две html-страницы для нашего проекта.

index.html
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <title>Hello, world!</title>
</head>
<body class="bg-light">

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Электронный деканат</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExample05"
            aria-controls="navbarsExample05" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarsExample05">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item">
                <a class="nav-link" href="#">Главная</a>
            </li>
            <li class="nav-item active">
                <a class="nav-link" href="#">Студенты <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Группы</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Кафедры</a>
            </li>

        </ul>
        <form class="form-inline mt-2 mt-md-0">
            <input class="form-control mr-sm-2" type="text" placeholder="Введите текст" aria-label="Search">
            <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Поиск</button>
        </form>
    </div>
</nav>

<div class="container">

    <div class="py-5 text-center">
        <h2>Управление студентами</h2>
        <p class="lead">На данной странице вы можете добавить, отредактировать поля или удалить студентов кафедры</p>
    </div>


    <div class="row">
        <div class="col">
            <h2>Группа АИ-171</h2>
        </div>
        <div class="col col-lg-3">
            <a th:href="@{~/add_student}" class="btn btn-lg btn-block btn-outline-primary" role="button"
               aria-disabled="true">Добавить студента</a>
        </div>
    </div>

    <br/>

    <div class="table-responsive">
        <table class="table table-striped">
            <thead>
            <tr>
                <th class="text-justify">#</th>
                <th class="text-justify">Фамилия</th>
                <th class="text-justify">Имя</th>
                <th class="text-justify">Отчество</th>
                <th class="text-justify">Почта</th>
                <th class="text-justify">Телефон</th>
                <th class="text-justify">Адрес</th>


            </tr>
            </thead>
            <tbody>

            <tr th:each="student : ${students}">
                <td class="align-middle"><span th:text="${student.id}"/></td>
                <td class="align-middle"><span th:text="${student.lastName}"/></td>
                <td class="align-middle"><span th:text="${student.firstName}"/></td>
                <td class="align-middle"><span th:text="${student.patronymic}"/></td>
                <td class="align-middle"><span th:text="${student.email}"/></td>
                <td class="align-middle"><span th:text="${student.phone}"/></td>
                <td class="align-middle"><span th:text="${student.address}"/></td>
            </tr>
            </tbody>
        </table>
    </div>
</div>

<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
        integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
        crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
        integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
        crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
        crossorigin="anonymous"></script>
</body>
</html>
add_student.html
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <title>Добавление студента</title>
</head>
<body class="bg-light">
<div class="container">
    <div class="py-5 text-center">
        <h2>Добавление студента</h2>
        <p class="lead">Заполните поля и нажмите кнопку 'Добавить студента'</p>
    </div>

    <form method="post" class="needs-validation" novalidate>
        <div class="row">
            <div class="col-md-12">
                <h4 class="mb-3">Поля для заполнения</h4>

                <div class="row">

                    <div class="col-md-4 mb-3">
                        <label for="lastName">Фамилия</label>
                        <input type="text" class="form-control" id="lastName" placeholder=""
                               value="" required>
                    </div>


                    <div class="col-md-4 mb-3">
                        <label for="firstName">Имя</label>
                        <input type="text" class="form-control" id="firstName" placeholder=""
                               value="" required>
                    </div>
                    <div class="col-md-4 mb-3">
                        <label for="patronymic">Отчество</label>
                        <input type="text" class="form-control" id="patronymic" placeholder=""
                               value="" required>
                    </div>
                </div>

                <div class="mb-3">
                    <label for="email">Электронная почта</label>
                    <input type="email" class="form-control" id="email"
                           placeholder="" value="" required>
                </div>

                <div class="mb-3">
                    <label for="phone">Телефон</label>
                    <input type="text" class="form-control" id="phone"
                           placeholder="(ХХХ) ХХХ-ХХХХ" value="" required>
                </div>

                <div class="mb-3">
                    <label for="address">Домашний адрес</label>
                    <input type="text" class="form-control" id="address" placeholder="" value=""
                           required>
                </div>

                <hr class="mb-4">
                <button class="btn btn-primary btn-lg btn-block" type="submit" value="Submit">Добавить студента</button>
    </form>
</div>
</div>
</div>

<br/><br/><br/>


<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
        integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
        crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
        integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
        crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
        crossorigin="anonymous"></script>
</body>
</html>

Создадим класс контроллера, который обрабатывает GET запросы с URL "/" и "/add_student".

StudentController.java
@Controller
public class StudentController {

    @GetMapping("/")
    public String index(Model model) {
        return "index";
    }

    @GetMapping("/add_student")
    public String addStudent(Model model) {
        return "add_student";
    }
}

В файле index.html добавим ссылку для кнопки "Добавить студента" . Для формирования ссылки используем тег th:href. Для указания пути относительно домена используем комбинацию @{~}.

index.html
        <div class="col col-lg-3">
            <a th:href="@{~/add_student}" class="btn btn-lg btn-block btn-outline-primary" role="button"
               aria-disabled="true">Добавить студента</a>
        </div>

Проверим работу приложения в браузере

Нажмем на кнопку "Добавить студента"

4. Получение данных формы

Для обработки формы необходимо выполнить следующую последовательность действий:

  1. Создать объект, поля которого будут содержать данные формы. В нашем случае создадим класс Student;

  2. Передать пустой объект Student при переходе на страницу формы;

  3. В полях формы настроить соответствие между полями формы и полями объекта класса Student;

  4. После отсылки формы заполненный объект Student передается в теле HTTP-запроса с методом POST, после чего заполненный объект можно обработать, сохранить в базе данных и так далее.

Создадим класс Student

Student.java
public class Student {

    private long id;
    private String lastName;
    private String firstName;
    private String patronymic;
    private String email;
    private String phone;
    private String address;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getPatronymic() {
        return patronymic;
    }

    public void setPatronymic(String patronymic) {
        this.patronymic = patronymic;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Student() {}

    public Student(String lastName, String firstName, String patronymic, String email, String phone, String address) {
        this.lastName = lastName;
        this.firstName = firstName;
        this.patronymic = patronymic;
        this.email = email;
        this.phone = phone;
        this.address = address;
    }
}

Изменим метод контроллера, который обрабатывает URL "/add_student". Передадим пустой объект студента

StudentController.java
@Controller
public class StudentController {

    ...

    @GetMapping("/add_student")
    public String addStudent(Model model) {
        model.addAttribute("student", new Student());
        return "add_student";
    }
}

Изменим файл add_student.html. В полях формы добавим привязку к полям объекта, в теге формы укажем название объекта (исходя из метода контроллера он должен называться "student", а также укажем URL для отправки данных формы).

add_student.html
<form enctype="multipart/form-data" action="#" th:action="@{/add_student}" th:object="${student}" method="post" class="needs-validation"
      novalidate>
    <div class="row">
        <div class="col-md-12">
            <h4 class="mb-3">Поля для заполнения</h4>

            <div class="row">

                <div class="col-md-4 mb-3">
                    <label for="lastName">Фамилия</label>
                    <input th:field="*{lastName}" type="text" class="form-control" id="lastName" placeholder=""
                           value="" required>
                </div>


                <div class="col-md-4 mb-3">
                    <label for="firstName">Имя</label>
                    <input th:field="*{firstName}" type="text" class="form-control" id="firstName" placeholder=""
                           value="" required>
                </div>
                <div class="col-md-4 mb-3">
                    <label for="patronymic">Отчество</label>
                    <input th:field="*{patronymic}" type="text" class="form-control" id="patronymic" placeholder=""
                           value="" required>
                </div>
            </div>

            <div class="mb-3">
                <label for="email">Электронная почта</label>
                <input th:field="*{email}" type="email" class="form-control" id="email"
                       placeholder="" value="" required>
            </div>

            <div class="mb-3">
                <label for="phone">Телефон</label>
                <input th:field="*{phone}" type="text" class="form-control" id="phone"
                       placeholder="(ХХХ) ХХХ-ХХХХ" value="" required>
            </div>

            <div class="mb-3">
                <label for="address">Домашний адрес</label>
                <input th:field="*{address}" type="text" class="form-control" id="address" placeholder="" value=""
                       required>
            </div>

            <hr class="mb-4">
            <button class="btn btn-primary btn-lg btn-block" type="submit" value="Submit">Добавить студента</button>
        </div>
    </div>
</form>

Создадим метод контроллера, который принимает POST-запрос с URL "/add_student". Данный метод будет обрабатывать результат заполнения формы.

StudentController.java
@Controller
public class StudentController {

    ...

    @PostMapping("/add_student")
    public String greetingSubmit(@ModelAttribute Student student) {
            return "redirect:/";
    }
}

Изменим класс Student, превратив его в сущность

Student.java
@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue
    private long id;

    private String lastName;
    private String firstName;
    private String patronymic;
    private String email;
    private String phone;
    private String address;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getPatronymic() {
        return patronymic;
    }

    public void setPatronymic(String patronymic) {
        this.patronymic = patronymic;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Student() {
    }

    public Student(String lastName, String firstName, String patronymic, String email, String phone, String address) {
        this.lastName = lastName;
        this.firstName = firstName;
        this.patronymic = patronymic;
        this.email = email;
        this.phone = phone;
        this.address = address;
    }
}

Создадим интерфейс репозитория

StudentRepository.java
public interface StudentRepository extends JpaRepository<Student,Long> {}

Добавим класс сервиса для работы с DAO

StudentService.java
@Service
public class StudentService {

    private StudentRepository repository;

    @Autowired
    public void setRepository(StudentRepository repository) {
        this.repository = repository;
    }

    public void saveStudent(Student student) {
        repository.save(student);
    }
}

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

StudentController.java
@Controller
public class StudentController {

    private StudentService service;

    @Autowired
    public void setService(StudentService service) {
        this.service = service;
    }

    ...

    @PostMapping("/add_student")
    public String greetingSubmit(@ModelAttribute Student student) {
        service.saveStudent(student);
        return "redirect:/";
    }
}

5. Вывод данных из БД

ля вывода данных на странице index, необходимо выполнить следующие действия:

  1. обратиться к базе данных для получения списка студентов;

  2. передать список студентов в View;

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

Модифицируем метод контроллера, который отвечает за обработку запроса "\"

StudentController.java
@Controller
public class StudentController {

    private StudentService service;

    @Autowired
    public void setService(StudentService service) {
        this.service = service;
    }
    
    @GetMapping("/")
    public String index(Model model) {
        model.addAttribute("students", service.getAllStudents());
        return "index";
    }
    
    ...
}

Модифицируем страницу index.html. Добавим вывод полей каждого объекта типа Student в таблице

index.html
<table class="table table-striped">
    <thead>
    <tr>
        <th class="text-justify">#</th>
        <th class="text-justify">Фамилия</th>
        <th class="text-justify">Имя</th>
        <th class="text-justify">Отчество</th>
        <th class="text-justify">Почта</th>
        <th class="text-justify">Телефон</th>
        <th class="text-justify">Адрес</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="student : ${students}">
        <td class="align-middle"><span th:text="${student.id}"/></td>
        <td class="align-middle"><span th:text="${student.lastName}"/></td>
        <td class="align-middle"><span th:text="${student.firstName}"/></td>
        <td class="align-middle"><span th:text="${student.patronymic}"/></td>
        <td class="align-middle"><span th:text="${student.email}"/></td>
        <td class="align-middle"><span th:text="${student.phone}"/></td>
        <td class="align-middle"><span th:text="${student.address}"/></td>
    </tr>
    </tbody>
</table>

Запустим приложение и посмотрим на результат. Изначально таблица студентов пустая

Добавляем нового студента

После добавления студента, нас перенаправляют на страницу index