Статьи

Интеграция Thymeleaf с Spring (часть 2)

1. Введение

Это вторая часть интеграции Thymeleaf с руководством Spring. Вы можете прочитать первую часть здесь , где вы узнаете, как настроить этот проект.

Как объяснялось в начале первой части этого руководства, веб-приложение будет отправлять два типа запросов:

  • Вставить нового гостя: отправляет синхронный запрос на сервер для добавления нового гостя. Это продемонстрирует, как Thymeleaf интегрируется с бобами поддержки формы Spring.
  • Список гостей: отправляет запрос AJAX, который обновит регион ( фрагмент ) страницы, чтобы показать список гостей, возвращенный с сервера.

Посмотрим, как мы этого добьемся.

2. Обработка форм

В этом разделе мы увидим, как форма отправляется с помощью Thymeleaf. Нам понадобятся три атрибута:

  1. го: действие
  2. го: объект
  3. го: поле

Первые два определены в элементе формы:

1
<form id="guestForm" th:action="@{/spring/guests/insert}" th:object="${guest}" method="post">

Атрибут th: action переписывает URL-адрес действия, добавляя к нему префикс контекста приложения.

Атрибут th: object в элементе формы — это выбор объекта. На него можно ссылаться в форме. Здесь мы привязываем компонент поддержки формы к атрибуту модели, который мы определили в контроллере перед рендерингом представления:

1
2
3
4
@ModelAttribute("guest")
public Guest prepareGuestModel() {
    return new Guest();
}

Как мы видим, th: object ссылается на компонент поддержки Гостевой формы, а th: field ссылается на его свойства. Посмотрите на форму тела:

01
02
03
04
05
06
07
08
09
10
11
<span class="formSpan">
    <input id="guestId" type="text" th:field="*{id}" required="required"/>
    <br />
    <label for="guestId" th:text="#{insert.id}">id:</label>
</span>
 
<span class="formSpan" style="margin-bottom:20px">
    <input id="guestName" type="text" th:field="*{name}" required="required"/>
    <br />
    <label for="guestName" th:text="#{insert.name}">name:</label>
</span>

Что th: field будет делать, так это присваивать значение своего входного элемента свойству bean-компонента. Таким образом, когда пользователь отправляет форму, все эти поля th: устанавливают свойства компонента поддержки формы.

На контроллере мы получим гостевой экземпляр:

1
2
3
4
5
6
@RequestMapping(value = "/guests/insert", method = RequestMethod.POST)
public String insertGuest(Guest newGuest, Model model) {
    hotelService.insertNewGuest(newGuest);
     
    return showHome(model);
}

Теперь гость может быть вставлен в базу данных.

3. Отправка запросов AJAX

Пытаясь найти простой пример отправки AJAX-запроса с Thymeleaf, я нашел примеры с Spring Webflow ( рендеринг фрагментов ). Я также читал, что другие говорят, что вам нужен Tiles для этого.

Я не хотел использовать эти фреймворки, поэтому в этом разделе я использую jQuery для отправки AJAX-запроса на сервер, ожидания ответа и частичного обновления представления (рендеринг фрагмента).

Форма

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<form>
    <span class="subtitle">Guest list form</span>
    <div class="listBlock">
        <div class="search-block">
            <input type="text" id="searchSurname" name="searchSurname"/>
            <br />
            <label for="searchSurname" th:text="#{search.label}">Search label:</label>
            <button id="searchButton" name="searchButton" onclick="retrieveGuests()" type="button"
                    th:text="#{search.button}">Search button</button>
        </div>
         
        <!-- Results block -->
        <div id="resultsBlock">
         
        </div>
    </div>
</form>

Эта форма содержит текст ввода со строкой поиска (searchSurname), которая будет отправлена ​​на сервер. Также есть регион (resultsBlock div), который будет обновляться в соответствии с ответом, полученным с сервера.

searchForm

Когда пользователь нажимает кнопку, вызывается функция retrieveGhest ().

1
2
3
4
5
6
7
8
9
function retrieveGuests() {
    var url = '/th-spring-integration/spring/guests';
     
    if ($('#searchSurname').val() != '') {
        url = url + '/' + $('#searchSurname').val();
    }
     
    $("#resultsBlock").load(url);
}

Функция загрузки jQuery делает запрос к серверу по указанному URL-адресу и помещает возвращенный HTML-код в указанный элемент (resultsBlock div).

Если пользователь вводит строку поиска, он будет искать всех гостей с указанной фамилией. В противном случае он вернет полный список гостей. Эти два запроса достигнут следующих отображений запросов контроллера:

01
02
03
04
05
06
07
08
09
10
11
12
13
@RequestMapping(value = "/guests/{surname}", method = RequestMethod.GET)
public String showGuestList(Model model, @PathVariable("surname") String surname) {
    model.addAttribute("guests", hotelService.getGuestsList(surname));
     
    return "results :: resultsList";
}
 
@RequestMapping(value = "/guests", method = RequestMethod.GET)
public String showGuestList(Model model) {
    model.addAttribute("guests", hotelService.getGuestsList());
     
    return "results :: resultsList";
}

Поскольку Spring интегрирован с Thymeleaf, он теперь сможет возвращать фрагменты HTML. В приведенном выше примере возвращаемая строка «results :: resultsList» ссылается на фрагмент с именем resultsList, который находится на странице результатов. Давайте посмотрим на эту страницу результатов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
    xmlns:th="http://www.thymeleaf.org" lang="en">
 
<head>
</head>
 
<body>
    <div th:fragment="resultsList" th:unless="${#lists.isEmpty(guests)}" class="results-block">
        <table>
            <thead>
                <tr>
                    <th th:text="#{results.guest.id}">Id</th>
                    <th th:text="#{results.guest.surname}">Surname</th>
                    <th th:text="#{results.guest.name}">Name</th>
                    <th th:text="#{results.guest.country}">Country</th>
                </tr>
            </thead>
            <tbody>
                <tr th:each="guest : ${guests}">
                    <td th:text="${guest.id}">id</td>
                    <td th:text="${guest.surname}">surname</td>
                    <td th:text="${guest.name}">name</td>
                    <td th:text="${guest.country}">country</td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
</html>

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

resultsBlock

4. Вывод

После интеграции обеих платформ мы узнали, как формы связаны с моделью Spring MVC. Мы также узнали, как отправлять запросы AJAX и частично обновлять представление.