Перейти к основному содержимому

Пример приложения с Spring Boot и Vaadin

· 5 мин. чтения

1. Обзор

Vaadin — это серверная среда Java для создания пользовательских веб-интерфейсов .

В этом руководстве мы рассмотрим, как использовать пользовательский интерфейс на основе Vaadin в бэкэнде на основе Spring Boot . Для ознакомления с Vaadin обратитесь к этому руководству.

2. Настройка

Начнем с добавления зависимостей Maven в стандартное приложение Spring Boot:

<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>

Vaadin также является признанной зависимостью Spring Initializer .

В этом руководстве используется более новая версия Vaadin, чем версия по умолчанию, введенная начальным модулем. Чтобы использовать более новую версию, просто определите спецификацию Vaadin Bill of Materials (BOM) следующим образом:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>10.0.11</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

3. Бэкэнд-сервис

Мы будем использовать сущность Employee со свойствами firstName и lastName для выполнения над ней операций CRUD:

@Entity
public class Employee {

@Id
@GeneratedValue
private Long id;

private String firstName;
private String lastName;
}

Вот простой соответствующий репозиторий Spring Data — для управления операциями CRUD:

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
List<Employee> findByLastNameStartsWithIgnoreCase(String lastName);
}

Мы объявляем метод запроса findByLastNameStartsWithIgnoreCase в интерфейсе EmployeeRepository . Он вернет список сотрудников , соответствующих lastName .

Давайте также предварительно заполним БД несколькими примерами Employee :

@Bean
public CommandLineRunner loadData(EmployeeRepository repository) {
return (args) -> {
repository.save(new Employee("Bill", "Gates"));
repository.save(new Employee("Mark", "Zuckerberg"));
repository.save(new Employee("Sundar", "Pichai"));
repository.save(new Employee("Jeff", "Bezos"));
};
}

4. Пользовательский интерфейс Ваадина

4.1. Класс MainView

Класс MainView является точкой входа для логики пользовательского интерфейса Vaadin. Аннотация @Route указывает Spring Boot автоматически подобрать его и показать в корне веб-приложения:

@Route
public class MainView extends VerticalLayout {
private EmployeeRepository employeeRepository;
private EmployeeEditor editor;
Grid<Employee> grid;
TextField filter;
private Button addNewBtn;
}

Мы можем настроить URL-адрес, по которому отображается представление, указав параметр в аннотации @Route :

@Route(value="myhome")

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

Редактор EmployeeEditor — показывает форму « Сотрудник », используемую для предоставления информации о сотруднике для создания и редактирования.

Grid<Employee> grid — гирд для отображения списка сотрудников .

TextField filter – текстовое поле для ввода фамилии, по которой будет фильтроваться гирд

Кнопка addNewBtn — кнопка для добавления нового сотрудника . Отображает редактор EmployeeEditor .

Он внутренне использует employeeRepository для выполнения операций CRUD.

4.2. Соединение компонентов вместе

MainView расширяет VerticalLayout . VerticalLayout — это контейнер компонентов, который показывает подкомпоненты в порядке их добавления (по вертикали).

Далее мы инициализируем и добавляем компоненты.

Мы даем метку кнопке со значком +.

this.grid = new Grid<>(Employee.class);
this.filter = new TextField();
this.addNewBtn = new Button("New employee", VaadinIcon.PLUS.create());

Мы используем HorizontalLayout для горизонтального размещения текстового поля фильтра и кнопки. Затем добавьте этот макет, сетку и редактор в родительский вертикальный макет:

HorizontalLayout actions = new HorizontalLayout(filter, addNewBtn);
add(actions, grid, editor);

Укажите высоту сетки и имена столбцов. Мы также добавляем текст справки в текстовое поле:

grid.setHeight("200px");
grid.setColumns("id", "firstName", "lastName");
grid.getColumnByKey("id").setWidth("50px").setFlexGrow(0);

filter.setPlaceholder("Filter by last name");

При запуске приложения пользовательский интерфейс будет выглядеть так:

./11312b2b9467bdd0bdb17d2d95d52c6d.png

4.3. Добавление логики к компонентам

Мы установим ValueChangeMode.EAGER в текстовое поле фильтра . Это синхронизирует значение с сервером каждый раз, когда оно изменяется на клиенте.

Мы также устанавливаем прослушиватель для события изменения значения, которое возвращает отфильтрованный список сотрудников на основе текста, предоставленного в фильтре:

filter.setValueChangeMode(ValueChangeMode.EAGER);
filter.addValueChangeListener(e -> listEmployees(e.getValue()));

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

grid.asSingleSelect().addValueChangeListener(e -> {
editor.editEmployee(e.getValue());
});

При нажатии кнопки «Добавить нового сотрудника» мы покажем пустую форму « Сотрудник »:

addNewBtn.addClickListener(e -> editor.editEmployee(new Employee("", "")));

Наконец, мы слушаем изменения, сделанные редактором, и обновляем сетку данными из бэкэнда:

editor.setChangeHandler(() -> {
editor.setVisible(false);
listEmployees(filter.getValue());
});

Функция listEmployees получает отфильтрованный список сотрудников и обновляет сетку:

void listEmployees(String filterText) {
if (StringUtils.isEmpty(filterText)) {
grid.setItems(employeeRepository.findAll());
} else {
grid.setItems(employeeRepository.findByLastNameStartsWithIgnoreCase(filterText));
}
}

4.4. Создание формы

Мы будем использовать простую форму для пользователя, чтобы добавить/редактировать сотрудника:

@SpringComponent
@UIScope
public class EmployeeEditor extends VerticalLayout implements KeyNotifier {

private EmployeeRepository repository;
private Employee employee;

TextField firstName = new TextField("First name");
TextField lastName = new TextField("Last name");

Button save = new Button("Save", VaadinIcon.CHECK.create());
Button cancel = new Button("Cancel");
Button delete = new Button("Delete", VaadinIcon.TRASH.create());

HorizontalLayout actions = new HorizontalLayout(save, cancel, delete);
Binder<Employee> binder = new Binder<>(Employee.class);
private ChangeHandler changeHandler;
}

@SpringComponent — это просто псевдоним аннотации Springs @Component , чтобы избежать конфликтов с классом компонентов Vaadins .

@UIScope связывает компонент с текущим пользовательским интерфейсом Vaadin .

В настоящее время отредактированный сотрудник хранится в переменной-члене сотрудника . Мы фиксируем свойства Employee через текстовые поля firstName и lastName .

На форме есть три кнопки – сохранить , отменить и удалить .

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

./b479f609c2cfb89f7a7f9012b01d3a7a.png

Мы используем Binder , который связывает поля формы со свойствами Employee , используя соглашение об именах :

binder.bindInstanceFields(this);

Мы вызываем соответствующий метод EmployeeRepositor на основе пользовательских операций:

void delete() {
repository.delete(employee);
changeHandler.onChange();
}

void save() {
repository.save(employee);
changeHandler.onChange();
}

5. Вывод

В этой статье мы написали полнофункциональное приложение CRUD с пользовательским интерфейсом, используя Spring Boot и Spring Data JPA для сохраняемости.

Как обычно, код доступен на GitHub .