Пример приложения с Spring Boot и Vaadin
1. обзор
2. Настроить
Начнем с добавления зависимостей Maven в стандартное приложение Spring Boot:
com.vaadin
vaadin-spring-boot-starter
Vaadin также является признанной зависимостьюSpring Initializer.
В этом руководстве используется более новая версия Vaadin, чем версия по умолчанию, введенная стартовым модулем. Чтобы использовать более новую версию, просто определите спецификацию Vaadin следующим образом:
com.vaadin
vaadin-bom
10.0.11
pom
import
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 {
List findByLastNameStartsWithIgnoreCase(String lastName);
}
Мы объявляем метод запросаfindByLastNameStartsWithIgnoreCase в интерфейсеEmployeeRepository. Он вернет списокEmployees, соответствующийlastName.
Давайте также предварительно заполним базу данных несколькими образцамиEmployees:
@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. Ваадин UI
4.1. MainView Класс
КлассMainView - это точка входа для логики пользовательского интерфейса Vaadin. Annotation @Route tells Spring Boot to automatically pick it up and show at the root of the web app:
@Route
public class MainView extends VerticalLayout {
private EmployeeRepository employeeRepository;
private EmployeeEditor editor;
Grid grid;
TextField filter;
private Button addNewBtn;
}
Мы можем настроить URL-адрес, в котором отображается представление, задав параметр аннотации@Route:
@Route(value="myhome")
Класс использует следующие компоненты пользовательского интерфейса для отображения на странице:
EmployeeEditor editor - показывает формуEmployee, используемую для предоставления информации о сотрудниках для создания и редактирования.
Grid<Employee> grid - пояс для отображения спискаEmployees
TextField filter - текстовое поле для ввода фамилии, по которой будет фильтроваться рундист
Button addNewBtn - Кнопка для добавления новогоEmployee. Отображает редакторEmployeeEditor.
Он внутренне используетemployeeRepository для выполнения операций CRUD.
4.2. Соединение компонентов вместе
MainView расширяетVerticalLayout. VerticalLayout is a component container, which shows the subcomponents in the order of their addition (по вертикали).
Далее мы инициализируем и добавляем компоненты.
Мы предоставляем ярлык для кнопки со значком +.
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");
При запуске приложения пользовательский интерфейс будет выглядеть так:
4.3. Добавление логики в компоненты
Мы установимValueChangeMode.EAGER в текстовое полеfilter. This syncs the value to the server each time it’s changed on the client.
Мы также устанавливаем прослушиватель для события изменения значения, которое возвращает отфильтрованный список сотрудников на основе текста, предоставленного вfilter:
filter.setValueChangeMode(ValueChangeMode.EAGER);
filter.addValueChangeListener(e -> listEmployees(e.getValue()));
При выборе строки в сетке мы показываем формуEmployee, позволяющую пользователю редактировать имя и фамилию:
grid.asSingleSelect().addValueChangeListener(e -> {
editor.editEmployee(e.getValue());
});
При нажатии кнопки добавления нового сотрудника отображается пустая формаEmployee:
addNewBtn.addClickListener(e -> editor.editEmployee(new Employee("", "")));
Наконец, мы слушаем изменения, внесенные редактором, и обновляем сетку данными из бэкэнда:
editor.setChangeHandler(() -> {
editor.setVisible(false);
listEmployees(filter.getValue());
});
ФункцияlistEmployees получает отфильтрованный списокEmployees и обновляет сетку:
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 binder = new Binder<>(Employee.class);
private ChangeHandler changeHandler;
}
The @SpringComponent is just an alias to Springs @Component annotation, чтобы избежать конфликтов с классом VaadinsComponent.
@UIScope связывает компонент с текущим пользовательским интерфейсом Vaadin.
В настоящее время отредактированныйEmployee хранится в переменной-членеemployee. Мы фиксируем свойстваEmployee через текстовые поляfirstName иlastName.
На форме есть три кнопки -save,cancel иdelete.
Как только все компоненты соединены вместе, форма будет выглядеть, как показано ниже:
Мы используемBinder which binds the form fields with the Employee properties using the naming convention:
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 для сохранения.
Как обычно, доступен кодover on GitHub.