原创

Spring Boot集成vaadin快速入门demo

1.什么是vaadin?

Vaadin 是用于构建单页 Web 应用的流行 Java 框架。 它由一家专门从事富 Internet 应用设计和开发的芬兰公司开发。 估计有 15 万开发者使用 Vaadin。 它的开发始于 2002 年。

Vaadin 框架特性

 

以下是 Vaadin 特性的列表:

  • 这是一个 Java Web 框架
  • 概念上类似于 Java Swing
  • 允许构建不带 HTML 和 JavaScript 的 Web 应用
  • 基于 Java Servlet 构建
  • 包含大量组件和窗口
  • 提供可定制的外观
  • 在客户端和服务器之间使用异步消息
  • 使用服务器端编程模型
  • 具有 Eclipse,NetBeans 和 IntelliJ 的插件
  • 使用 Google Web Toolkit 呈现结果网页
  • 提升代码质量和安全性

2.代码工程

实验目标

用嵌入式数据库h2存储数据,用vaadin构建crud操作界面,使用jpa操作h2数据库

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
        <relativePath/>
        <!--  lookup parent from repository  -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>vaadin</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <vaadin.version>24.3.13</vaadin.version>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>


    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <version>24.3.8</version> <!-- check latest version -->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

view

主视图类(MainView本指南中称为)是 Vaadin 的 UI 逻辑的入口点。在 Spring Boot 应用程序中,如果您使用 对其进行注释@Route,它将自动被拾取并显示在 Web 应用程序的根目录中。您可以通过为注释提供参数来自定义显示视图的 URL @Route
package com.et.vaadin.view;

import com.et.vaadin.entity.Customer;
import com.et.vaadin.repository.CustomerRepository;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.Route;
import org.springframework.util.StringUtils;

@Route
public class MainView extends VerticalLayout {

   private final CustomerRepository repo;

   private final CustomerEditor editor;

   final Grid<Customer> grid;

   final TextField filter;

   private final Button addNewBtn;

   public MainView(CustomerRepository repo, CustomerEditor editor) {
      this.repo = repo;
      this.editor = editor;
      this.grid = new Grid<>(Customer.class);
      this.filter = new TextField();
      this.addNewBtn = new Button("New customer", VaadinIcon.PLUS.create());

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

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

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

      // Hook logic to components

      // Replace listing with filtered content when user changes filter
      filter.setValueChangeMode(ValueChangeMode.LAZY);
      filter.addValueChangeListener(e -> listCustomers(e.getValue()));

      // Connect selected Customer to editor or hide if none is selected
      grid.asSingleSelect().addValueChangeListener(e -> {
         editor.editCustomer(e.getValue());
      });

      // Instantiate and edit new Customer the new button is clicked
      addNewBtn.addClickListener(e -> editor.editCustomer(new Customer("", "")));

      // Listen changes made by the editor, refresh data from backend
      editor.setChangeHandler(() -> {
         editor.setVisible(false);
         listCustomers(filter.getValue());
      });

      // Initialize listing
      listCustomers(null);
   }

   // tag::listCustomers[]
   void listCustomers(String filterText) {
      if (StringUtils.hasText(filterText)) {
         grid.setItems(repo.findByLastNameStartsWithIgnoreCase(filterText));
      } else {
         grid.setItems(repo.findAll());
      }
   }
   // end::listCustomers[]

}
由于 Vaadin UI 是纯 Java 代码,因此您可以从头开始编写可重复使用的代码。为此,请为您的Customer实体定义一个编辑器组件。您可以将其设为 Spring 管理的 bean,以便您可以直接将其注入CustomerRepository编辑器并处理创建、更新和删除部分或您的 CRUD 功能
package com.et.vaadin.view;

import com.et.vaadin.entity.Customer;
import com.et.vaadin.repository.CustomerRepository;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.Route;
import org.springframework.util.StringUtils;

@Route
public class MainView extends VerticalLayout {

   private final CustomerRepository repo;

   private final CustomerEditor editor;

   final Grid<Customer> grid;

   final TextField filter;

   private final Button addNewBtn;

   public MainView(CustomerRepository repo, CustomerEditor editor) {
      this.repo = repo;
      this.editor = editor;
      this.grid = new Grid<>(Customer.class);
      this.filter = new TextField();
      this.addNewBtn = new Button("New customer", VaadinIcon.PLUS.create());

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

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

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

      // Hook logic to components

      // Replace listing with filtered content when user changes filter
      filter.setValueChangeMode(ValueChangeMode.LAZY);
      filter.addValueChangeListener(e -> listCustomers(e.getValue()));

      // Connect selected Customer to editor or hide if none is selected
      grid.asSingleSelect().addValueChangeListener(e -> {
         editor.editCustomer(e.getValue());
      });

      // Instantiate and edit new Customer the new button is clicked
      addNewBtn.addClickListener(e -> editor.editCustomer(new Customer("", "")));

      // Listen changes made by the editor, refresh data from backend
      editor.setChangeHandler(() -> {
         editor.setVisible(false);
         listCustomers(filter.getValue());
      });

      // Initialize listing
      listCustomers(null);
   }

   // tag::listCustomers[]
   void listCustomers(String filterText) {
      if (StringUtils.hasText(filterText)) {
         grid.setItems(repo.findByLastNameStartsWithIgnoreCase(filterText));
      } else {
         grid.setItems(repo.findAll());
      }
   }
   // end::listCustomers[]

}

entity

package com.et.vaadin.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

@Entity
public class Customer {

   @Id
   @GeneratedValue
   private Long id;

   private String firstName;

   private String lastName;

   protected Customer() {
   }

   public Customer(String firstName, String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
   }

   public Long getId() {
      return id;
   }

   public String getFirstName() {
      return firstName;
   }

   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }

   public String getLastName() {
      return lastName;
   }

   public void setLastName(String lastName) {
      this.lastName = lastName;
   }

   @Override
   public String toString() {
      return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id,
            firstName, lastName);
   }

}

repository

package com.et.vaadin.repository;

import com.et.vaadin.entity.Customer;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

/**
 * @author liuhaihua
 * @version 1.0
 * @ClassName CustomerRepository
 * @Description todo
 */
public interface CustomerRepository extends JpaRepository<Customer, Long> {

    List<Customer> findByLastNameStartsWithIgnoreCase(String lastName);
}

application.yaml

server:
  port: 8088
package com.et.vaadin;

import com.et.vaadin.entity.Customer;
import com.et.vaadin.repository.CustomerRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication

public class DemoApplication {
   private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @Bean
   public CommandLineRunner loadData(CustomerRepository repository) {
      return (args) -> {
         // save a couple of customers
         repository.save(new Customer("Jack", "Bauer"));
         repository.save(new Customer("Chloe", "O'Brian"));
         repository.save(new Customer("Kim", "Bauer"));
         repository.save(new Customer("David", "Palmer"));
         repository.save(new Customer("Michelle", "Dessler"));

         // fetch all customers
         log.info("Customers found with findAll():");
         log.info("-------------------------------");
         for (Customer customer : repository.findAll()) {
            log.info(customer.toString());
         }
         log.info("");

         // fetch an individual customer by ID
         Customer customer = repository.findById(1L).get();
         log.info("Customer found with findOne(1L):");
         log.info("--------------------------------");
         log.info(customer.toString());
         log.info("");

         // fetch customers by last name
         log.info("Customer found with findByLastNameStartsWithIgnoreCase('Bauer'):");
         log.info("--------------------------------------------");
         for (Customer bauer : repository
               .findByLastNameStartsWithIgnoreCase("Bauer")) {
            log.info(bauer.toString());
         }
         log.info("");
      };
   }
}

3.测试

启动Spring Boot应用,

测试crud操作

访问地址http://127.0.0.1:8088/ vaadin-list  

4.引用

   
正文到此结束
Loading...