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

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™

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PHP蜜语翻译器在线文字转码解码源码

源码介绍 PHP蜜语翻译器在线文字转码解码源码 文字加密通话、一键转换、蜜语密码 无需数据库,可以将文字、字母、数字、代码、表情、标点符号等内容转换成新的文字形式&#xff0c;通过简单的文字以不同的排列顺序来表达不同的内容&#xff01;支持在线加密解密 有多种加密展示…

物联网技术-第3章物联网感知技术-3.2定位技术

目录 1.1位置信息和位置服务 1.1.1位置信息 1.1.2位置服务 1.2主流定位系统 1.2.1卫星定位系统&#xff08;Satellite Positioning Systems&#xff09; 1.2.2移动通信蜂窝基站定位&#xff08;Cellular Triangulation or Advanced Forward Link Trilateration&#xff09…

使用 Iceberg、Tabular 和 MinIO 构建现代数据架构

现代数据环境需要一种新型的基础架构&#xff0c;即无缝集成结构化和非结构化数据、轻松扩展并支持高效的 AI/ML 工作负载的基础架构。这就是现代数据湖的用武之地&#xff0c;它为您的所有数据需求提供了一个中心枢纽。然而&#xff0c;构建和管理有效的数据湖可能很复杂。 这…

MySQL之优化服务器设置和复制(一)

优化服务器设置 操作系统状态 CPU密集型的机器 CPU密集型服务器的vmstat输出通常在us列会有一个很高的值&#xff0c;报告了花费在非内核代码上的CPU时钟;也可能在sy列有很高的值&#xff0c;表示系统CPU利用率&#xff0c;超过20%就足以令人不安了。在大部分情况下&#xff…

无代码爬虫软件八爪鱼采集器-如何设计判断是、否

我们在设计采集规则的时候&#xff0c;可能会需要判断&#xff0c;比如采集评论的时候“展开更多回复”&#xff0c;就点击这个按钮&#xff0c;像这种情况就可以设计一个判断模块进入 判断模块添加后会自动生成两个&#xff0c;默认都是不判断直接执行&#xff0c;如果我们需要…

网络安全:数据库安全性

文章目录 网络安全&#xff1a;数据库安全性引言数据库安全性的重要性常见的数据库安全威胁数据库安全性的最佳实践数据加密访问控制审计和监控 结语 网络安全&#xff1a;数据库安全性 引言 在前两篇文章中&#xff0c;我们讨论了SQL注入的概念和防范措施。本篇文章将聚焦于…

记一次线上jVM调优

文章目录 问题描述问题分析尝试优化业务代码优化方案修改后代码补充点 问题描述 部门调整&#xff0c;接手一个新项目&#xff0c;为方便后续描述叫user-web&#xff0c;随后推动IT降本&#xff0c;要求根据实际业务量调整服务器实例数量和配置&#xff0c;调整前服务器配置为…

【DevOps】Elasticsearch 数据跨集群同步方案

目录 1、Elasticsearch Cross-Cluster Replication (CCR) 1.1、优点 1.2、缺点 1.3、步骤 1.4、示例 2. Logstash 或其他 ETL 工具 2.1、优点 2.2、缺点 2.3、步骤 3. Apache Kafka 或 RabbitMQ 3.1、优点 3.2、缺点 3.3、步骤 4、使用 Reindex API 进行跨集群同…

基于 Thingsboard 定制开发,国产化企业级、低代码 AIoT 物联网平台

项目源码&#xff0c;文末联系小编 01 ThingsKit 物联网平台 ThingsKit 是基于 Thingsboard 开源物联网平台二次开发&#xff0c;面向中小型企业开箱即用的低代码物联网平台&#xff0c;提供N1N&#xff08;N个终端产品1个物联网平台N个行业方案&#xff09;的产品服务矩阵&…

2024爱分析·AI Agent创新成就奖开启申报丨奖项征集

AI Agent正成为企业数字化转型的关键力量。它们不仅提升了工作效率&#xff0c;优化了客户体验&#xff0c;更是在数据分析、决策支持和自动化流程中扮演着至关重要的角色。随着技术的不断进步和应用场景的拓展&#xff0c;AI Agent正以其独特优势&#xff0c;引领企业进入一个…

我的第一个 iOS 程序:iTahDoodle

我的第一个 iOS 程序&#xff1a;iTahDoodle 我的第一个 iOS 程序&#xff1a;iTahDoodle应用功能对象图应用委托对象设置视图为按钮关联动作方法为 UITableView 对象提供数据保存并加载任务数据在模拟器上运行程序下载链接 我的第一个 iOS 程序&#xff1a;iTahDoodle 实现了…

QT——MySQL数据库联用

一、ODBC 1、ODBC简介 ODBC全称为Open Database Connectivity,是一种用于数据库操作的标准接口。要使用ODBC,首先需要安装相应的ODBC驱动程序,然后在系统中配置ODBC数据源。接着,可以通过编程语言(如C++、Java等)或者数据库工具(如SQL Server Management Studio)来连…

深度学习推理显卡设置

深度学习推理显卡设置 进入NVIDIA控制面板&#xff0c;选择 “管理3D设置”设置 "低延时模式"为 "“超高”"设置 “电源管理模式” 为 “最高性能优先” 使用锁频来获得稳定的推理 法一&#xff1a;命令行操作 以管理员身份打开CMD查看GPU核心可用频率&…

AIoT设备新一代高性能处理器瑞芯微RK3576,东胜物联RK3588等核心板定制开发

随着物联网、人工智能和嵌入式技术的不断发展&#xff0c;智能设备应用对芯片处理器的性能需求越来越高&#xff0c;以满足复杂的数据处理需求、实时性要求、复杂的算法运算和多任务处理能力。高性能的芯片可以为智能设备提供更强大的计算能力和更快速的响应速度&#xff0c;从…

通过nginx转发后应用偶发502bad gateway

序言 学习了一些东西&#xff0c;如何才是真正自己能用的呢&#xff1f;好像就是看自己的潜意识的反应&#xff0c;例如解决了一个问题&#xff0c;那么下次再碰到类似的问题&#xff0c;能直接下意识的去找到对应的信息&#xff0c;从而解决&#xff0c;而不是和第一次碰到一样…

新手如何入门Web3?

一、什么是Web3&#xff1f; Web3是指下一代互联网&#xff0c;它基于区块链技术&#xff0c;致力于将各种在线活动变得更加安全、透明和去中心化。Web3是一个广义的概念&#xff0c;涵盖了包括数字货币、去中心化应用、智能合约等在内的多个方面。它的主要特点包括去中心化、…

网络编程--网络理论基础(二)

这里写目录标题 网络通信流程mac地址、ip地址arp协议交换机路由器简介子网划分网关 路由总结 为什么ip相同的主机在与同一个互联网服务通信时不冲突公网ip对于同一个路由器下的不同设备&#xff0c;虽然ip不冲突&#xff0c;但是因为都是由路由器的公网ip转发通信&#xff0c;接…

Apache Paimon系列之:Append Table和Append Queue

Apache Paimon系列之&#xff1a;Append Table和Append Queue 一、Append Table二、Data Distribution三、自动小文件合并四、Append Queue五、压缩六、Streaming Source七、Watermark Definition八、Bounded Stream 一、Append Table 如果表没有定义主键&#xff0c;则默认为…

Vue3基础介绍

文章目录 一、简介1、简介2、性能提升3、源码升级4、拥抱TypeScript5、新特性 二、创建Vue3.0工程1、使用vue-cli创建2、使用vite创建 三、分析工程结构1、main.js2、组件中 一、简介 1、简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号(One Piece)海贼王 …

怎么用AI绘画完成设计创作?

AI绘画工具为设计师提供了强大的功能和便利性&#xff0c;用AI绘画进行艺术创作能够使设计师能够更快地迭代和优化设计方案&#xff0c;提高设计效率。那么怎么用AI绘画完成设计创作? 要使用AI绘画完成设计创作&#xff0c;首先需要选择一个合适的工具。目前市场上有很多优秀的…