教程:使用 Spring Boot 构建全栈反应式聊天应用

您将构建的内容

您将构建一个全栈聊天应用程序,其中包含Java Spring Boot后端,Project Reactor中的反应式数据类型和Lit TypeScript前端。此外,您将使用 Hilla 框架来构建工具和客户端-服务器通信。

您将需要什么

  • 20 分钟
  • Java 11 或更高版本
  • 节点 16.14 或更高版本
  • 同时支持 Java 和 TypeScript 的 IDE,例如 VS Code。

创建新项目

首先创建一个新的 Hilla 项目。这将为您提供一个配置了 Lit 前端的 Spring Boot 项目。

  1. 使用 Vaadin CLI 初始化项目:npx @vaadin/cli init --hilla --empty hilla-chat
  2. 在所选的 IDE 中打开项目。
  3. 使用随附的 Maven 包装器启动应用程序。该命令将下载 Maven 和 npm 依赖项并启动开发服务器。注意:初始启动可能需要几分钟时间。 后续启动几乎是即时的。./mvnw

构建聊天视图

首先创建用于显示和发送聊天消息的视图。Hilla包括Vaadin组件集,它有40多个组件。您将使用 和 组件来构建主聊天 UI。您还将使用该组件来捕获当前用户的名称。

将 的内容替换为以下内容:frontend/views/empty/empty-view.ts

import { html } from 'lit';brimport { customElement } from 'lit/decorators.js';brimport { View } from '../../views/view';brimport '@vaadin/vaadin-messages';brimport '@vaadin/vaadin-text-field';brbr@customElement('empty-view')brexport class EmptyView extends View {br  render() {br    return html`br      br      br        br        br      br    `;br  }brbr  connectedCallback() {br    super.connectedCallback();br    this.classList.add('flex', 'flex-col', 'h-full', 'box-border');br  }br}

Hilla 使用 Lit 创建视图。Lit在概念上类似于React:组件由一个状态和一个模板组成。每当状态更改时,模板都会重新呈现。

除了包含的Vaadin组件之外,您还可以使用Hilla CSS实用程序类进行一些基本的布局(,,)。flexflex-growflex-col

保存文件时,您应该会看到一个空窗口,底部有输入。(如果未运行服务器,则 启动服务器。./mvnw

创建无反应式服务器端点

接下来,您需要一个可以在客户端之间代理消息的后端。为此,您将使用 Project Reactor 提供的反应式数据类型。

在调用的包中创建一个新的 Java 类,并将以下代码粘贴到其中:com.example.applicationChatEndpoint.java

package com.example.application;brbrimport java.time.ZonedDateTime;brimport com.vaadin.flow.server.auth.AnonymousAllowed;brimport dev.hilla.Endpoint;brimport dev.hilla.Nonnull;brimport reactor.core.publisher.Flux;brimport reactor.core.publisher.Sinks;brimport reactor.core.publisher.Sinks.EmitResult;brimport reactor.core.publisher.Sinks.Many;brbr@Endpointbr@AnonymousAllowedbrpublic class ChatEndpoint {brbr  public static class Message {br    public @Nonnull String text;br    public ZonedDateTime time;br    public @Nonnull String userName;br  }brbr  private Many chatSink;br  private Flux chat;brbr  ChatEndpoint() {br    chatSink = Sinks.many().multicast().directBestEffort();br    chat = chatSink.asFlux().replay(10).autoConnect();br  }brbr  public @Nonnull Flux<@Nonnull Message> join() {br    return chat;br  }brbr  public void send(Message message) {br    message.time = ZonedDateTime.now();br    chatSink.emitNext(message,br        (signalType, emitResult) -> emitResult == EmitResult.FAIL_NON_SERIALIZED);br  }br}br

以下是解释的基本部分:

  • 注释告诉 Hilla 使所有公共方法都作为客户端的 TypeScript 方法提供。 关闭此终结点的身份验证。@Endpoint@AnonymousAllowed
  • Message 类是数据模型的普通 Java 对象。注释告诉 TypeScript 生成器,这些类型不应为 null。@Nonnull
  • 这是一种将数据传递到系统的编程方式。它发出消息,以便订阅相关 Flux 的任何客户端都将收到这些消息。chatSinkchat
  • -方法返回聊天 Flux,您将在客户端上订阅该聊天 Flux。join()
  • -方法接收消息,用发送时间标记该消息,然后将其发送到 .send()chatSink

在客户端中发送和接收消息

后端就位后,剩下的唯一事情就是将前端视图连接到服务器。

将 的内容替换为以下内容:empty-view.ts

import { html } from 'lit';brimport { customElement, state } from 'lit/decorators.js';brimport { View } from '../../views/view';brimport '@vaadin/vaadin-messages';brimport '@vaadin/vaadin-text-field';brimport Message from 'Frontend/generated/com/example/application/ChatEndpoint/Message';brimport { ChatEndpoint } from 'Frontend/generated/endpoints';brimport { TextFieldChangeEvent } from '@vaadin/vaadin-text-field';brbr@customElement('empty-view')brexport class EmptyView extends View {br  @state() messages: Message[] = [];br  @state() userName = '';brbr  render() {br    return html`br      br      br        br        br      br    `;br  }brbr  userNameChange(e: TextFieldChangeEvent) {br    this.userName = e.target.value;br  }brbr  submit(e: CustomEvent) {br    ChatEndpoint.send({br      text: e.detail.value,br      userName: this.userName,br    });br  }brbr  connectedCallback() {br    super.connectedCallback();br    this.classList.add('flex', 'flex-col', 'h-full', 'box-border');br    ChatEndpoint.join().onNext(br      (message) => (this.messages = [...this.messages, message])br    );br  }br}

以下是解释的基本部分:

  • 装饰物业由Lit跟踪。每当它们发生更改时,模板都会重新呈现。@state()
  • 数据类型由 Hilla 根据您在服务器上创建的 Java 对象生成。Message
  • 消息列表通过 绑定到消息列表组件。项前面的句点告诉 Lit 将数组作为属性而不是特性传递。.items=${this.messages}
  • 每当值更改为 (表示事件侦听器)时,文本字段都会调用 -method。userNameChange@change=${this.userNameChange}@
  • 消息输入组件在提交时调用。请注意,您正在调用 TypeScript 方法。Hilla 负责在服务器上调用底层 Java 方法。ChatEndpoint.save()
  • 最后,致电开始接收传入的聊天消息。ChatEndpoint.join()connectedCallback

保存文件时,您会注意到浏览器窗口的右下角弹出一条警告。单击它以启用 Hilla 中的推送支持功能标志。此功能标志支持通过 Web 套接字连接订阅 Flux 数据类型。

运行已完成的应用程序

启用推送支持功能标志后,停止正在运行的服务器 () 并重新运行它 ()。您现在有一个功能强大的聊天应用程序。通过以第二个用户身份打开第二个浏览器或隐身窗口来尝试一下。CTRL-C./mvnw

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章