Spring Boot集成vaadin快速入门demo

news2024/12/28 18:39:07

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

DemoApplication.java

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("");
      };
   }
}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo

3.测试

启动Spring Boot应用,

测试crud操作

访问地址http://127.0.0.1:8088/

vaadin-list

 

4.引用

  • Tutorial: Building Modern Web Applications With Spring Boot and Vaadin
  • Spring Boot集成vaadin快速入门demo | Harries Blog™

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1850125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

这周,接连两位程序员猝死...

这周接连发生了两起不幸的事。俩位程序员去世的消息&#xff0c;深感悲伤和惋惜。 6月17号下午&#xff0c;一位负责研发的女员工在虾皮研发中心办公室猝死&#xff0c;年仅 30 岁。 官方通告&#xff1a; 同一天&#xff0c;另一位科大讯飞的高级测试工程师在家突发不适离世…

修改文件的权限(linux篇)

1.在yl用户下创建一个demo.txt文件 [rootlocalhost ~]# su yl [yllocalhost root]$ cd [yllocalhost ~]$ cd Desktop/ [yllocalhost Desktop]$ ls [yllocalhost Desktop]$ vim demo.txt 填入一些信息进行保存 2.查看文件信息以及所对应的组 [yllocalhost Desktop]$ ll 总用量…

一颗B+树可以存储多少数据?

一、前言 这个问题&#xff0c;非常经典&#xff0c;考察的点很多&#xff1a; 比如&#xff1a; 1、操作系统存储的单元&#xff0c;毕竟mysql也是运行在操作系统之上的应用。 2、B树是针对Mysql的InnoDB存储引擎&#xff0c;所以要理解InnoDb的最小存储单元&#xff0c;页&…

解两道四年级奥数题(等差数列)玩玩

1、1&#xff5e;200这200个连续自然数的全部数字之和是________。 2、2&#xff0c;4&#xff0c;6&#xff0c;……&#xff0c;2008这些偶数的所有各位数字之和是________。 这两道题算易错吧&#xff0c;这里求数字之和&#xff0c;比如124这个数的全部数字之和是1247。 …

【yolov8语义分割】跑通:下载yolov8+预测图片+预测视频

1、下载yolov8到autodl上 git clone https://github.com/ultralytics/ultralytics 下载到Yolov8文件夹下面 另外&#xff1a;现在yolov8支持像包一样导入&#xff0c;pip install就可以 2、yolov8 语义分割文档 看官方文档&#xff1a;主页 -Ultralytics YOLO 文档 还能切…

使用 DISPATCHERS 进行 Blueprint 之间的通信

文章目录 初始准备DISPATCHERS 的创建和绑定实现效果 初始准备 首先 UE5 默认是不提供 静态网格体编辑器也就是 Modeling Mode 的&#xff0c;这里需要从插件中添加 Modeling Tools Editor Mode 进入 Modeling Mode 模式&#xff0c;创建一个正方体 然后利用 PolyGroup Edit 和…

告别手抖尴尬!教你轻松缓解手部震颤的小秘诀!

在我们的日常生活中&#xff0c;手抖这个现象可能并不罕见。不论是因为紧张、疲劳还是某些健康问题&#xff0c;手抖都会给我们的生活带来诸多不便。今天&#xff0c;就让我们一起探讨如何缓解手部震颤&#xff0c;让你告别手抖的尴尬&#xff01; 一、手抖的成因及影响 手抖&…

定点计算与浮点计算在MCU上的较量:以电机控制系统算法实现为例

在嵌入式系统尤其是电机控制算法的实现过程中&#xff0c;定点计算与浮点计算的选取始终是一个重要议题。电机控制系统对实时性和计算效率有着极高要求&#xff0c;而MCU&#xff08;微控制器&#xff09;作为其核心处理器&#xff0c;其计算模式的选择直接影响整个系统的性能。…

pycharm中的使用技巧

1、更改主题&#xff1a;找到设置&#xff0c;然后更改主题 点击选择自己喜欢的主题&#xff0c;然后就可以更改主题了 2、设置字体的快捷键 找到设置&#xff0c;如下&#xff1a; 找到increase&#xff0c;如下&#xff1a; 右键选择&#xff0c;增加字体快捷键 按住ctrl滑轮…

压缩包文件密码破解软件 Ziperello 下载及使用教程

使用 Ziperello https://qweree.cn/index.php/416/ 对加了密码的压缩包进行密码破解&#xff0c;教程如下&#xff1a; 第一步&#xff0c;双击运行 Ziperello双击我打开程序.exe&#xff0c;如下图&#xff1a; 第二步&#xff0c;打开一个加了密的 ZIP 压缩包&#xff0c;再…

LCR 142.训练计划IV

1.题目要求: /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ int compare(const void* a,const void* b) {return (*(int*)a - *(int*)b); } struct ListNode* trainningPlan(struct ListNode* l1, struct Li…

Linux驱动开发笔记(十三)Sysfs文件系统

文章目录 前言一、Sysfs1.1 Sysfs的引入1.2 Sysfs的目录结构1.2 Sysfs的目录详解1.2.1 devices1.2.2 bus1.2.3 class1.2.4 devices、bus、class目录之间的关系1.2.5 其他子目录 二、Sysfs使用2.1 核心数据结构2.2 相关函数2.2.1 kobject_create_and_add2.2.2 kobject_put()2.2.…

转让5000万内资融资租赁公司变更需要的条件和变更时间

我们现在有一家陕西的融资租赁公司公司是非常干净的非常适合接手后直接开展业务如果北京的不能够变更了我们这边还有渠道可以变更现在能做的越来越少了&#xff0c;详情流程致电咨询或者来我们公司面谈。 现成融资租赁公司转让&#xff1a; 1、公司名称&#xff1a;陕西xxX融资…

【龙晰 离线安装openssl-devel】openssl-devel rpm 离线安装 需要下载哪些安rpm 包

进入龙晰镜像源地址下载 http://mirrors.openanolis.cn/anolis/8/BaseOS/x86_64/os/Packages/(base) [rootAI lib64]# yum install openssl-devel Last metadata expiration check: 14:03:32 ago on Fri 21 Jun 2024 07:26:56 AM CST. Dependencies resolved. Package …

Linux扩展lvm分区实践 -- 使用其他磁盘的空间

如图&#xff0c;根分区900G&#xff0c;计划将另一块磁盘sdb分出1T来给根分区 步骤 1&#xff1a;创建新的分区 sudo fdisk /dev/sdb输入 n 创建一个新分区 然后选择分区类型&#xff0c;输入p 设置起始扇区&#xff08;默认&#xff09;&#xff0c;然后设置分区大小&…

nginx启动之后任务管理器里面没有nginx进程

原因1&#xff1a;确保你的nginx文件夹里面只包含英文路径&#xff01;绝对不能有中文&#xff01; 原因2&#xff1a; 到conf\nginx.conf里面查看端口和IP地址是否正确设置&#xff0c;ip地址有无正确输入

MySQL之复制(十)

复制 改变主库 确定期望的日志位置 如果有备库和新主库的位置不相同&#xff0c;则需要找到该备库最后一条执行的时间在新主库的二进制日志中相应的位置&#xff0c;然后再执行CHANGE MASTER TO.可以通过mysqlbinlog工具来找到备库执行的最后一条查询&#xff0c;然后在主库上…

JupyterLab使用指南(二):JupyterLab基础

第2章 JupyterLab基础 2.1 JupyterLab界面介绍 JupyterLab的用户界面非常直观和灵活。它包括文件浏览器、工作区、多标签页、命令面板和侧边栏等功能。以下是各个部分的详细介绍&#xff1a; 2.1.1 文件浏览器 文件浏览器位于界面左侧&#xff0c;用于导航和管理文件。你可…

【英伟达GPU的挑战者】Groq—AI大模型推理的革命者

目录 引言第一部分&#xff1a;Groq简介第二部分&#xff1a;Groq的特点与优势1、高性能推理加速2、近存计算技术3、专用ASIC芯片设计4、低延迟与高吞吐量5、成本效益分析6、易用性与集成性7、软件与硬件的协同设计 第三部分&#xff1a;Groq的使用指南1、准备工作2、简单使用样…

<Rust><iced>在iced中显示gif动态图片的一种方法

前言 本文是在rust的GUI库iced中在窗口显示动态图片GIF格式图片的一种方法。 环境配置 系统&#xff1a;window 平台&#xff1a;visual studio code 语言&#xff1a;rust 库&#xff1a;iced、image 概述 在iced中&#xff0c;提供了image部件&#xff0c;从理论上说&…