在本文中,我们学习了 Hilla 开发的基础知识,用于构建全栈 Web 应用程序,该应用程序结合了 Spring Boot 后端和 React 前端并具有类型安全的通信。
Hilla 让我们将 React 视图添加到 Spring Boot 项目中。视图根据名称和文件夹结构映射到路由。我们可以从 TypeScript 调用 Spring Service类,通过使用 @BrowserCallable 注释Service类来保留完整的类型信息。Hilla使用 Java Bean Validation 注释在客户端进行输入验证,并再次验证 Java 服务方法中收到的数据的正确性。
Hilla 是一个 Java 的全栈 Web 框架。通过向Spring Boot应用程序添加 React 视图并通过类型安全的 RPC 从 TypeScript 调用后端 Java 服务, Hilla 使我们能够构建全栈应用程序。
它使用Vaadin UI 组件集并与Vaadin Flow兼容。两者都是 Vaadin 平台的一部分。在本教程中,我们将讨论 Hilla 开发的基础知识。
创建 Hilla 项目
我们可以通过在 Spring Initializr 上添加 Vaadin 依赖或在 Vaadin Start 上下载定制的启动器来创建 Hilla 项目。
或者,我们可以将 Hilla 添加到现有的 Spring Boot 项目中,方法是在项目的Maven pom.xml中添加以下物料清单 (BOM) 。我们使用最新版本的vaadin-bom初始化vaadin.version属性:
<properties> |
然后,我们为 Vaadin 平台添加以下依赖项,其中包括 Hilla:
<dependency> |
为了完成设置,让我们创建一个主题。主题配置文件确保所有视图的外观一致,并包含CSS 实用程序类。我们添加一个src/main/frontend/themes/hilla/theme.json文件,其中包含以下内容:
{ |
然后,我们通过更新 Spring Boot 应用程序来扩展AppShellConfigurator并添加@Theme(“hilla”)注释来加载主题:
@Theme("hilla") // needs to match theme folder name |
启动应用程序
Hilla 将 React 视图和后端 Java 源代码包含在同一个项目中,作为一个统一的全栈项目。我们可以通过在src/main/frontend/views文件夹中创建 React 组件来定义视图。
让我们首先通过创建一个新文件src/main/frontend/views/@index.tsx (根据需要创建文件夹)来添加视图,其内容如下:
export default function Index() { |
现在,让我们通过运行mvn spring-boot:run或在我们的 IDE 中运行 Spring Boot 应用程序类来启动应用程序。
首次启动需要一些时间,因为 Hilla 需要下载 Maven 和 npm 依赖项并启动 Vite 开发服务器。后续启动会更快。
随着构建的运行,我们可以打开浏览器到localhost:8080来查看“ Hello world ”问候语:
显示“Hello world”文本的浏览器窗口
使用@BrowserCallable调用服务器方法
Hilla 应用程序的一个独特之处在于我们如何从客户端调用服务器。与带有 React 前端的传统 Spring Boot 应用程序不同,我们不会创建两个通过通用 REST API 进行通信的独立应用程序。相反,我们有一个全栈应用程序,它使用 RPC 调用用 Java 编写的服务类上的方法。它遵循后端前端 (BFF) 架构。
让我们看看如何从浏览器访问后端服务。我们将在整个示例中使用Contact类:
@Entity |
我们还将使用Spring Data JPA存储库来访问和保存数据:
public interface ContactRepository extends |
我们可以通过用@BrowserCallable注释来使 Java 服务可从 TypeScript 视图调用。Hilla 服务受Spring Security保护。默认情况下,所有服务均被拒绝访问。我们可以添加 @AnonymousAllowed注释以允许任何用户调用该服务:
@BrowserCallable |
Java 和 TypeScript 对可空性的处理方式不同。在 Java 中,所有非原始类型都可以为空,而 TypeScript 要求我们明确将变量或字段定义为可空。Hilla的 TypeScript 生成器默认处于严格模式,确保 Java 和 TypeScript 类型完全匹配。
这种严格的缺点是 TypeScript 代码可能会变得笨拙,因为我们需要在几个地方引入空检查。如果我们遵循良好的 API 设计实践,避免集合返回空值,我们可以在服务包中添加带有@NonnullApi注释的package-info.java文件,以简化 TypeScript 类型:
@NonNullApi |
现在,我们可以从 React 调用具有相同签名的服务。让我们更新@index.tsx以查找所有联系人并将其显示在Grid中:
export default function Contacts() { |
让我们定义一个异步函数fetchContacts(),它等待ContactService.findAll(),然后将 contacts 信号值设置为接收到的联系人。我们从Frontend/generated文件夹导入Contact类型和ContactService,这是 Hilla 生成客户端代码的地方。
配置视图和布局
Hilla 使用基于文件的路由,这意味着视图根据其文件名和文件夹结构映射到路由。所有视图的根文件夹是src/main/frontend/views。在以下部分中,我们将介绍如何配置视图和布局。
视图命名约定
视图通过其名称和以下约定映射到路径:
- @index.tsx — 目录的索引
- @layout.tsx — 目录的布局
- view-name.tsx — 映射到view-name
- {parameter} — 捕获参数的文件夹
- {parameter}.tsx — 捕获参数的视图
- {{parameter}}.tsx — 捕获可选参数的视图
- {…wildcard}.tsx — 匹配任意字符
查看配置
我们可以通过导出类型为ViewConfig的常量 config 来配置视图。在这里,我们可以定义视图的标题、图标和访问控制等内容:
export const config: ViewConfig = { |
定义布局
我们可以为任何目录定义父布局。views文件夹根目录中的@layout.tsx包装应用程序中的所有内容,而contacts文件夹中的@layout.tsx仅包装该目录或其子目录中的任何视图。
让我们在src/main/frontend/views目录中创建一个新的@layout.tsx文件:
export default function MainLayout() { |
createMenuItems ()助手返回已发现路线的数组并为每个路线创建链接。
让我们再次打开浏览器并验证我们是否可以在视图上方看到新菜单:
浏览器窗口在联系人视图顶部显示导航菜单
创建表单并验证输入
接下来,让我们实现编辑视图来编辑联系人。我们将使用 Hilla useForm()钩子将输入字段绑定到联系人对象上的字段,并验证其上定义的所有验证约束是否通过。
首先,我们创建一个新文件views/contacts/{id}/edit.tsx, 内容如下:
export default function ContactEditor() { |
然后,让我们使用useParams()钩子从 URL访问id参数。
接下来,我们将ContactModel传递给useForm()并将其配置为提交给我们的 Java 服务。我们还将解构field、model、submit,并将返回值中的属性读取到变量中。最后,我们使用useEffect将当前选定的联系人读入表单,该 useEffect从后端按id获取联系人。
我们为Contact上的每个属性创建输入字段,并使用字段方法将它们绑定到Contact对象上的相应字段。这会将 Java 对象上定义的值和验证规则与 UI 同步。
使用 AutoCrud 自动执行 CRUD 操作
由于 Hilla 是一个全栈框架,它可以帮助我们自动执行一些常见任务,例如创建列表和编辑实体。让我们更新我们的服务以利用这些功能:
@BrowserCallable |
扩展CrudRepositoryService会创建一个服务,该服务提供 Hilla 需要的所有基本 CRUD 操作,以便根据给定实体生成数据网格、表单或 CRUD 视图。在本例中,我们还添加了之前在服务中使用的相同的findAll()和findById()方法,以避免破坏现有视图。
现在,我们可以创建一个新视图,该视图显示基于新服务的 CRUD 编辑器。让我们定义一个名为frontend/views/auto-crud.tsx的新文件 ,其内容如下:
export default function AutoCrudView() { |
我们只需要返回一个组件AutoCrud,并传入服务和模型来获取列出、编辑和删除联系人的视图:
浏览器窗口左侧显示联系人列表。列表中选定的联系人以表格形式显示在右侧。如果我们只需要列出项目而不进行编辑,则可以使用AutoGrid组件。同样,如果我们需要编辑项目但不想显示列表,则可以使用AutoForm组件。两者的工作方式与上面的AutoCrud相同。
生产构建
为了构建 Hilla 以供生产使用,我们使用生产Maven 配置文件。生产构建会创建一个优化的前端 JavaScript 包并关闭开发时调试。该配置文件会自动包含在 Spring Initializr 和 Vaadin Start 上创建的项目中。如果我们有自定义项目,我们也可以手动添加它:
<profile> |
我们可以使用生产配置文件构建项目:
./mvnw package -Pproduction