«1. Обзор

Vaadin — это серверная среда Java для создания пользовательских веб-интерфейсов. Используя его, мы можем создать наш интерфейс, используя функции Java.

2. Зависимости и настройка Maven

Начнем с добавления следующих зависимостей в наш pom.xml:

<dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-server</artifactId>
</dependency>
<dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-client-compiled</artifactId>
</dependency>
<dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-themes</artifactId>
</dependency>

Последние версии зависимостей можно найти здесь: vaadin-server, vaadin-client- скомпилированные, vaadin-темы.

    Пакет vaadin-server — включает классы для обработки всех деталей сервера, таких как сеансы, взаимодействие с клиентом и т. д. vaadin-client-compiled — основан на GWT и включает необходимые пакеты для компиляции клиентских тем vaadin — – включает некоторые готовые темы и все утилиты для создания наших тем

Чтобы скомпилировать наши виджеты Vaadin, нам нужно настроить плагины maven-war, vaadin-maven-plugin и maven-clean-plugin. Для полного pom обязательно проверьте файл pom в исходном коде — в конце руководства.

Также нам нужно добавить репозиторий Vaadin и управление зависимостями:

<repositories>
    <repository>
        <id>vaadin-addons</id>
        <url>http://maven.vaadin.com/vaadin-addons</url>
    </repository>
</repositories>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-bom</artifactId>
            <version>13.0.9</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Тег DependencyManagement управляет версиями всех зависимостей Vaadin.

Для быстрого запуска приложения воспользуемся плагином Jetty:

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>9.3.9.v20160517</version>
    <configuration>
        <scanIntervalSeconds>2</scanIntervalSeconds>
        <skipTests>true</skipTests>
    </configuration>
</plugin>

Последнюю версию плагина можно найти здесь: jetty-maven-plugin.

С помощью этого плагина мы можем запустить наш проект с помощью команды:

mvn jetty:run

3. Что такое Vaadin?

Проще говоря, Vaadin — это Java-фреймворк для создания пользовательских интерфейсов с темами и компонентами, а также множеством вариантов расширения.

Фреймворк также охватывает серверную часть, а это означает, что каждое изменение, которое вы вносите в пользовательский интерфейс, немедленно отправляется на сервер, поэтому внутреннее приложение в любой момент знает, что происходит во внешнем интерфейсе.

Vaadin состоит из клиентской и серверной частей, при этом клиентская часть построена на основе хорошо известного фреймворка Google Widget Toolkit, а серверная часть обрабатывается VaadinServlet.

4. Сервлет

Обычно приложение Vaadin не использует файл web.xml; вместо этого он определяет свой сервлет с помощью аннотаций:

@WebServlet(urlPatterns = "/VAADIN/*", name = "MyUIServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = VaadinUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {}

В этом случае этот сервлет обслуживает содержимое из пути /VAADIN.

5. Основной класс

Класс VaadinUI, на который ссылается сервлет, должен расширять класс пользовательского интерфейса из фреймворка и должен переопределять метод init, чтобы завершить загрузку приложения с включенным Vaadin.

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

public class VaadinUI extends UI {

    @Override
    protected void init(VaadinRequest vaadinRequest) {
        VerticalLayout verticalLayout = new VerticalLayout();
        verticalLayout.setSpacing(true);
        verticalLayout.setMargin(true);
        setContent(verticalLayout);
}

6. Менеджеры макетов Vaadin

Фреймворк поставляется с рядом предопределенных менеджеров макетов.

6.1. VerticalLayout

Сложите компоненты в столбец, где первый добавленный находится вверху, а последний — внизу:

VerticalLayout verticalLayout = new VerticalLayout();
verticalLayout.setSpacing(true);
verticalLayout.setMargin(true);
setContent(verticalLayout);

Обратите внимание, что свойства здесь частично заимствованы из типичной терминологии CSS.

6.2. HorizontalLayout

Этот макет размещает каждый компонент рядом слева направо, как и вертикальный макет:

HorizontalLayout horizontalLayout = new HorizontalLayout();

6.3. GridLayout

Этот макет помещает каждый виджет в сетку, вам нужно передать в качестве параметра столбцы и строки сетки:

GridLayout gridLayout = new GridLayout(3, 2);

6.4. FormLayout

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

FormLayout formLayout = new FormLayout();

7. Компоненты Vaadin

Теперь, когда макет обработан, давайте посмотрим в некоторых из наиболее распространенных компонентов для построения нашего пользовательского интерфейса.

7.1. Метка

Метка, конечно, также хорошо известна и просто используется для отображения текста:

Label label = new Label();
label.setId("LabelID");
label.setValue("Label Value");
label.setCaption("Label");
gridLayout.addComponent(label);

После того, как мы создадим компонент, обратите внимание на критический шаг добавления его в макет.

7.2. Ссылка

Виджет ссылки, по сути, представляет собой простую гиперссылку:

Link link = new Link("Baeldung",
  new ExternalResource("http://www.baeldung.com/"));
link.setTargetName("_blank");

Обратите внимание, что здесь представлены типичные HTML-значения элемента \u003ca\u003e.

7.3. TextField

Этот виджет используется для ввода текста:

TextField textField = new TextField();
textField.setIcon(VaadinIcons.USER);

Мы можем дополнительно настроить элементы; например, мы можем быстро добавлять изображения к виджетам с помощью API setIcon().

Также обратите внимание, что Font Awesome поставляется вместе с фреймворком; он определен как Enum, и мы можем легко его использовать.

7.4. Текстовая Область

«Как и следовало ожидать, TextArea доступен рядом с остальными традиционными элементами HTML:

TextArea textArea = new TextArea();

7.5. DateField и InlineDateField

Этот мощный компонент используется для выбора дат; параметр date — это текущая дата, которую нужно выбрать в виджете:

DateField dateField = new DateField("DateField", LocalDate.ofEpochDay(0));

Мы можем пойти дальше и вложить его в поле со списком для экономии места:

InlineDateField inlineDateField = new InlineDateField();

7.6. PasswordField

Это стандартный ввод пароля в маске:

PasswordField passwordField = new PasswordField();

7.7. RichTextArea

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

RichTextArea richTextArea = new RichTextArea();
richTextArea.setCaption("Rich Text Area");
richTextArea.setValue("<h1>RichTextArea</h1>");
richTextArea.setSizeFull();
Panel richTextPanel = new Panel();
richTextPanel.setContent(richTextArea);

7.8. Кнопка

Кнопки используются для ввода данных пользователем и бывают разных размеров и цветов.

Чтобы создать кнопку, мы создаем экземпляр класса виджета, как обычно:

Button normalButton = new Button("Normal Button");

Изменяя стиль, мы можем иметь несколько разных кнопок:

tinyButton.addStyleName("tiny");
smallButton.addStyleName("small");
largeButton.addStyleName("large");
hugeButton.addStyleName("huge");
dangerButton.addStyleName("danger");
friendlyButton.addStyleName("friendly");
primaryButton.addStyleName("primary");
borderlessButton.addStyleName("borderless");
linkButton.addStyleName("link");
quietButton.addStyleName("quiet");

Мы можем создать отключенную кнопку:

Button disabledButton = new Button("Disabled Button");
disabledButton.setDescription("This button cannot be clicked");
disabledButton.setEnabled(false);
buttonLayout.addComponent(disabledButton);

Нативная кнопка, использующая внешний вид браузера:

NativeButton nativeButton = new NativeButton("Native Button");
buttonLayout.addComponent(nativeButton);

И кнопка со значком:

Button iconButton = new Button("Icon Button");
iconButton.setIcon(VaadinIcons.ALIGN_LEFT);
buttonLayout.addComponent(iconButton);

7.9. CheckBox

Флажок является элементом изменения состояния, установлен или снят:

CheckBox checkbox = new CheckBox("CheckBox");        
checkbox.setValue(true);
checkbox.addValueChangeListener(e ->
  checkbox.setValue(!checkbox.getValue()));
formLayout.addComponent(checkbox);

7.10. Списки

У Vaadin есть несколько полезных виджетов для работы со списками.

Во-первых, мы создаем список наших элементов, которые будут помещены в виджет:

List<String> numbers = new ArrayList<>();
numbers.add("One");
numbers.add("Ten");
numbers.add("Eleven");

ComboBox представляет собой раскрывающийся список:

ComboBox comboBox = new ComboBox("ComboBox");
comboBox.addItems(numbers);
formLayout.addComponent(comboBox);

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

ListSelect listSelect = new ListSelect("ListSelect");
listSelect.addItems(numbers);
listSelect.setRows(2);
formLayout.addComponent(listSelect);

NativeSelect похож на ComboBox, но имеет внешний вид браузера:

NativeSelect nativeSelect = new NativeSelect("NativeSelect");
nativeSelect.addItems(numbers);
formLayout.addComponent(nativeSelect);

TwinColSelect представляет собой двойной список, в котором мы можем менять элементы между этими двумя панелями; каждый элемент может одновременно находиться только в одной из панелей:

TwinColSelect twinColSelect = new TwinColSelect("TwinColSelect");
twinColSelect.addItems(numbers);

7.11. Сетка

Сетка используется для отображения данных прямоугольным образом; у вас есть строки и столбцы, вы можете определить верхний и нижний колонтитулы для данных:

Grid<Row> grid = new Grid(Row.class);
grid.setColumns("column1", "column2", "column3");
Row row1 = new Row("Item1", "Item2", "Item3");
Row row2 = new Row("Item4", "Item5", "Item6");
List<Row> rows = new ArrayList();
rows.add(row1);
rows.add(row2);
grid.setItems(rows);

Приведенный выше класс Row представляет собой простой POJO, который мы добавили для представления строки:

public class Row {
    private String column1;
    private String column2;
    private String column3;

    // constructors, getters, setters
}

8. Server Push ~~ ~ Еще одна интересная функция — возможность отправлять сообщения с сервера в пользовательский интерфейс.

Чтобы использовать push-уведомление сервера, нам нужно добавить следующую зависимость в наш pom.xml:

Последнюю версию зависимости можно найти здесь: vaadin-push.

<dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-push</artifactId>
    <versionId>8.8.5</versionId>
</dependency>

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

Мы создаем метку для захвата push-сообщения сервера:

@Push
@Theme("mytheme")
public class VaadinUI extends UI {...}

Затем мы создаем ScheduledExecutorService, который отправляет время от сервера до метки:

private Label currentTime;

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

ScheduledExecutorService scheduleExecutor = Executors.newScheduledThreadPool(1);
Runnable task = () -> {
    currentTime.setValue("Current Time : " + Instant.now());
};
scheduleExecutor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS);

9. Привязка данных

Мы можем привязать наш пользовательский интерфейс к нашим бизнес-классам.

Сначала мы создаем класс Java:

Затем мы привязываем наш класс, который имеет одно поле, к TextField в нашем пользовательском интерфейсе:

public class BindData {

    private String bindName;

    public BindData(String bindName){
        this.bindName = bindName;
    }
    
    // getter & setter
}

Сначала мы создаем объект BindData, используя класс класс, который мы создали ранее, то Binder привязывает поле к TextField.

Binder<BindData> binder = new Binder<>();
BindData bindData = new BindData("BindData");
binder.readBean(bindData);
TextField bindedTextField = new TextField();
binder.forField(bindedTextField).bind(BindData::getBindName, BindData::setBindName);

10. Валидаторы

Мы можем создать Валидаторы для проверки данных в наших полях ввода. Для этого мы присоединяем валидатор к полю, которое хотим проверить:

Затем мы проверяем наши данные перед их использованием:

BindData stringValidatorBindData = new BindData("");
TextField stringValidator = new TextField();
Binder<BindData> stringValidatorBinder = new Binder<>();
stringValidatorBinder.setBean(stringValidatorBindData);
stringValidatorBinder.forField(stringValidator)
  .withValidator(new StringLengthValidator("String must have 2-5 characters lenght", 2, 5))
  .bind(BindData::getBindName, BindData::setBindName);

В этом случае мы используем StringLengthValidator, который проверяет длина строки, но Vaadin предоставляет другие полезные валидаторы, а также позволяет нам создавать собственные валидаторы.

Button buttonStringValidator = new Button("Validate String");
buttonStringValidator.addClickListener(e -> stringValidatorBinder.validate());

11. Резюме

Конечно, этот краткий обзор едва затронул поверхность; фреймворк — это гораздо больше, чем виджеты пользовательского интерфейса, Vaadin предоставляет все необходимое для создания современных веб-приложений с использованием Java.

И, как всегда, код можно найти на Github.

«