1. Overview
1.概述
Vaadin is a server-side Java framework for creating web user interfaces.
Vaadin是一个用于创建Web用户界面的服务器端Java框架。
In this tutorial, we’ll explore how to use a Vaadin based UI on a Spring Boot based backend. For an introduction to Vaadin refer to this tutorial.
在本教程中,我们将探讨如何在基于Spring Boot的后端使用基于Vaadin的UI。有关Vaadin的介绍,请参考本教程。
2. Setup
2.设置
Let’s start by adding Maven dependencies to a standard Spring Boot application:
让我们先在一个标准的Spring Boot应用程序中添加Maven依赖项。
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>
Vaadin is also a recognized dependency by the Spring Initializer.
Vaadin也是一个被Spring Initializer认可的依赖关系。。
This tutorial uses a newer version of Vaadin than the default one brought in by the starter module. To use the newer version, simply define the Vaadin Bill of Materials (BOM) like this:
本教程使用的是一个较新的Vaadin版本,而不是启动模块带来的默认版本。要使用较新的版本,只需像这样定义Vaadin的物料清单(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. Backend Service
3.后端服务
We’ll use an Employee entity with firstName and lastName properties to perform CRUD operations on it:
我们将使用一个带有firstName和lastName属性的Employee实体来对其进行CRUD操作。
@Entity
public class Employee {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
}
Here’s the simple, corresponding Spring Data repository – to manage the CRUD operations:
这里有一个简单的、对应的Spring Data仓库–管理CRUD操作。
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
List<Employee> findByLastNameStartsWithIgnoreCase(String lastName);
}
We declare query method findByLastNameStartsWithIgnoreCase on the EmployeeRepository interface. It will return the list of Employees matching the lastName.
我们在EmployeeRepository接口上声明查询方法findByLastNameStartsWithIgnoreCase。它将返回符合lastName的Employee列表。
Let’s also pre-populate the DB with a few sample Employees:
让我们也用几个样本雇员来预先填充DB。
@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. Vaadin UI
4.我需要用户界面
4.1. MainView Class
4.1.MainView类
The MainView class is the entry point for Vaadin’s UI logic. Annotation @Route tells Spring Boot to automatically pick it up and show at the root of the web app:
MainView类是Vaadin的UI逻辑的入口。注解@Route告诉Spring Boot自动拾取它并显示在Web应用程序的根部:
@Route
public class MainView extends VerticalLayout {
private EmployeeRepository employeeRepository;
private EmployeeEditor editor;
Grid<Employee> grid;
TextField filter;
private Button addNewBtn;
}
We can customize the URL where the view is shown by giving a parameter to the @Route annotation:
我们可以通过给@Route注释一个参数来定制显示视图的URL。
@Route(value="myhome")
The class uses following UI components to be displayed on the page:
该类使用以下UI组件在页面上显示。
EmployeeEditor editor – shows the Employee form used to provide employee information to create and edit.
EmployeeEditor编辑器 – 显示Employee表格,用于提供雇员信息的创建和编辑。
Grid<Employee> grid – gird to display the list of Employees
Grid<Employee> grid – 显示Employees的列表。
TextField filter – text field to enter the last name based on which the gird will be filtered
TextField filter – 输入姓氏的文本字段,将根据该字段进行过滤。
Button addNewBtn – Button to add a new Employee. Displays the EmployeeEditor editor.
Button addNewBtn – 添加新雇员的按钮。显示EmployeeEditor编辑器。
It internally uses the employeeRepository to perform the CRUD operations.
它内部使用employeeRepository来执行CRUD操作。
4.2. Wiring the Components Together
4.2.将部件连在一起的接线
MainView extends VerticalLayout. VerticalLayout is a component container, which shows the subcomponents in the order of their addition (vertically).
MainView扩展了VerticalLayout。VerticalLayout是一个组件容器,它按添加顺序显示子组件(垂直)。
Next, we initialize and add the components.
接下来,我们初始化并添加组件。
We provide a label to the button with a + icon.
我们为该按钮提供一个带有 “+”图标的标签。
this.grid = new Grid<>(Employee.class);
this.filter = new TextField();
this.addNewBtn = new Button("New employee", VaadinIcon.PLUS.create());
We use HorizontalLayout to horizontally arrange filter text field and the button. Then add this layout, gird, and editor into the parent vertical layout:
我们使用HorizontalLayout来水平排列过滤文本字段和按钮。然后将这个布局、腰带和编辑器添加到父级垂直布局中。
HorizontalLayout actions = new HorizontalLayout(filter, addNewBtn);
add(actions, grid, editor);
Provide the gird height and column names. We also add help text in the text field:
提供腰围高度和列名。我们还在文本字段中添加帮助文本。
grid.setHeight("200px");
grid.setColumns("id", "firstName", "lastName");
grid.getColumnByKey("id").setWidth("50px").setFlexGrow(0);
filter.setPlaceholder("Filter by last name");
On the application startup, UI would look this:
在应用程序启动时,用户界面会是这样的。
4.3. Adding Logic to Components
4.3.为组件添加逻辑
We’ll set ValueChangeMode.EAGER to the filter text field. This syncs the value to the server each time it’s changed on the client.
我们将把ValueChangeMode.EAGER设为filter文本字段。这样,每次在客户端上改变数值时,都会同步到服务器上。
We also set a listener for the value change event, which returns the filtered list of employees based on the text provided in the filter:
我们还为价值变化事件设置了一个监听器,它根据过滤器中提供的文本返回过滤后的雇员名单:。
filter.setValueChangeMode(ValueChangeMode.EAGER);
filter.addValueChangeListener(e -> listEmployees(e.getValue()));
On selecting a row within the gird, we would show the Employee form, allowing the user to edit the first name and last name:
在选择腰带内的一行时,我们将显示雇员表格,允许用户编辑名字和姓氏。
grid.asSingleSelect().addValueChangeListener(e -> {
editor.editEmployee(e.getValue());
});
On clicking the add new employee button, we would show the blank Employee form:
在点击添加新员工按钮时,我们将显示空白的员工表格。
addNewBtn.addClickListener(e -> editor.editEmployee(new Employee("", "")));
Finally, we listen to the changes made by the editor and refresh the grid with data from the backend:
最后,我们听从编辑器的变化,用后台的数据刷新网格。
editor.setChangeHandler(() -> {
editor.setVisible(false);
listEmployees(filter.getValue());
});
The listEmployees function gets the filtered list of Employees and updates the grid:
listEmployees函数获取过滤后的Employees列表并更新网格。
void listEmployees(String filterText) {
if (StringUtils.isEmpty(filterText)) {
grid.setItems(employeeRepository.findAll());
} else {
grid.setItems(employeeRepository.findByLastNameStartsWithIgnoreCase(filterText));
}
}
4.4. Building the Form
4.4.构建表格
We’ll use a simple form for the user to add/edit an employee:
我们将使用一个简单的表单让用户添加/编辑一个雇员。
@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;
}
The @SpringComponent is just an alias to Springs @Component annotation to avoid conflicts with Vaadins Component class.
@SpringComponent只是Spring @Component注解的一个别名,以避免与Vaadins Component类的冲突。
The @UIScope binds the bean to the current Vaadin UI.
@UIScope将Bean绑定到当前的Vaadin UI。
Currently, edited Employee is stored in the employee member variable. We capture the Employee properties through firstName and lastName text fields.
目前,编辑过的Employee被存储在employee成员变量中。我们通过firstName和lastName文本字段捕获Employee属性。
The form has three button – save, cancel and delete.
该表格有三个按钮 – 保存,取消和删除。
Once all the components are wired together, the form would look as below for a row selection:
一旦所有的组件被连接在一起,表格看起来就像下面的行选择。
We use a Binder which binds the form fields with the Employee properties using the naming convention:
我们使用一个Binder,它使用命名惯例将表单字段与Employee属性绑定起来:。
binder.bindInstanceFields(this);
We call the appropriate EmployeeRepositor method based on the user operations:
我们根据用户的操作,调用适当的EmployeeRepositor方法。
void delete() {
repository.delete(employee);
changeHandler.onChange();
}
void save() {
repository.save(employee);
changeHandler.onChange();
}
5. Conclusion
5.结论
In this article, we wrote a full-featured CRUD UI application using Spring Boot and Spring Data JPA for persistence.
在这篇文章中,我们使用Spring Boot和Spring Data JPA编写了一个全功能的CRUD UI应用程序,用于持久性。
As usual, the code is available over on GitHub.
像往常一样,代码可在GitHub上获得。