关键要点
- Hilla 有望显著提高开源框架 Web 开发效率的应用程序。
- 它将 Spring Boot Java 后端和响应式 TypeScript 前端集成在一起。
- 使用用户界面 Lit 或 React 以及 Vaadin 的 40 多个开源 UI Web 创建组件。
- Hilla 帮助更快地构建业务应用程序,通过类型安全的服务器通信和集成工具。
- Hilla 它还自动为客户端生成 REST API 以及访问代码。
- 默认情况下,后端安全,完全无状态。
以简化为目的 Web 应用程序开发的框架,Hilla 在开源社区脱颖而出。它结合了 Spring Boot Java 后端和反应 TypeScript 前端,通过 Lit 或 React 进行的 UI 能够创建动态应用程序的设计。Vaadin 的 40 多个开源 UI Web 该组件进一步增强了它,为优秀的用户体验提供了随时可用的元素。
Hilla 高度重视效率和安全性,自动生成 API 默认与客户端访问代码,确保后端安全。本文将进行深入探讨 Hilla 核心方面:是的 Lit、Spring Bean 使用端点、前端和后端角色以及路由视图。这些观点将有助于开发人员利用它们 Hilla 加快构建强大的业务应用程序。以下是 Hilla 如何通过 Lit、Spring Bean 几个提高开发人员效率的例子,如端点、前端和后端角色以及路由视图。
希拉Hilla框架由芬兰公司制作 Vaadin 该公司还维护着同名的开发 Java Web 框架 Vaadin Flow。
与使用纯 Java 方法的 Vaadin Flow 不同,Hilla 是一个经典的单页应用程序 (SPA) 专注于全栈开发的框架。
这意味着客户端正在使用 TypeScript 开发的。可以使用前端 Lit 框架或 React,目前只使用后端 Spring Boot,但我们正在努力支持其他人 Java框架。
Hilla 项目是纯的 Maven 项目。在底层,Hilla Maven 插件使用 npm 前端构建与Vite相结合。
然而,与传统的前端开发不同,你不必担心这些工具的配置和运行,这大大简化了前端开发的开始,特别是对 Java 对开发人员而言。
点燃Hilla 支持客户端 Lit 和 React。本文将重点介绍我 Lit,因为它是 Hilla 使用的第一个客户端框架。Lit 是着名的 Polymer 库 [Polymer] 用于快速开发Web的继承者 Components。使用 Lit,所谓的自定义组件可以开发,即 HTML 语言的扩展。模板通过声明包含在模板中 TypeScript 也可以在代码中添加仅 Web 组件在上下文中有效 CSS。Web 当发生变化时,组件的属性是反应性的,并自动重新呈现。
@customElement('simple-greeting')export class SimpleGreeting extends LitElement { @property() name?: string = 'World'; render() { return html`<p>Hello, ${this.name}!</p>`; }}
代码图 1:带有 Lit 的组件
图 1 要注意的关键是@customElement
装饰器中的名称必须包含连字符才能与标准相匹配 HTML 区分元素。装饰@property
该装置使字符串名称成为一种反应属性,可以从组件外部设置,并在更改过程中重新显示组件。这个render()
方法为 Web 组件生成模板。在生成中 DOM 在中间,可以找到组件,如图所示 2 所示。
<body> <simple-greeting name="World"></simple-greeting></body>
代码图像 2:呈现的 Web 组件
端点在后端,Hilla 使用所谓的端点。端点是一种用途 注释的 Spring Bean@Endpoint
。由此,Hilla 生成一个 REST API,包括 TypeScript 在客户端访问代码。
@Endpoint@AnonymousAllowedpublic class HelloWorldEndpoint { @Nonnull public String sayHello(@Nonnull String name) { if (name.isEmpty()) { return "Hello stranger"; } else { return "Hello " + name; } }}
代码图 3:端点
在图 3 首先要注意的是@AnonymousAllowed
注释。此注释可以访问,无需身份验证。 API 这是必要的,因为默认情况下是必要的 Hilla 所有端点都受到保护。@Nonnull
还应注意注释。因为 TypeScript 对 null 的处理比 Java 更严格,可以通知 TypeScript 生成器参数和返回值永远不应该是null
.
function _sayHello(name: string): Promise<string> { return client.call('HelloWorldEndpoint', 'sayHello', {name});}export { _sayHello as sayHello };
代码图 4:生成的 TypeScript 代码
图 4 显示生成的可在前端使用 TypeScript 代码。如果端点、参数或返回类型发生任何变化,代码将重新生成,并在客户端上报告相应的错误。这有助于检测开发过程 API 使用中的错误。
示例应用程序该应用程序将显示一个个人数据表,可以用表单编辑。将使用个人数据 JPA 存储在数据库中。图 1 显示结果。在GitHub上发布示例代码。
图 1:带表格的网格
命令行界面在创建 Hilla 开发人员需要在应用程序之前安装NodeJS16.14 或者更高的版本。之后,Vaadin CLI 可以与 npx 共同创建新项目。CLI 形成一个完整的 Hilla 应用程序,带Hello-World-View
和HelloWorldEndpoint
来自图像 3。
npx @vaadin/cli init --hilla hilla-app
代码图 5:CLI
后端首先,Person
添加一个叫做实体的实体。使用此示例 JPA 保存数据 H2 数据库中。
@Entitypublic class Person { @Id @GeneratedValue private Long id; @NotBlank private String firstName; @NotBlank private String lastName; @Email @NotBlank private String email; ...}
代码图 6:人物实体
如图 6 所示,已使用 Jakarta Bean 验证注释。Hilla 生成器也考虑到了这一点。如果在客户端表单中使用 Person 实体将根据注释验证输入(图) 2)。
图 2:验证
下一步,为读取和保存人员数据创建端点。PersonRepository
图 7 中使用的 SpringDatatata扩展 JPAJpaRepository
接口。
@Endpoint@AnonymousAllowedpublic class PersonEndpoint { @Autowired private PersonRepository personRepository; @Nonnull public List<@Nonnull Person> findAll() { return personRepository.findAll(); } public void save(@Nonnull Person person) { this.personRepository.save(person); }}
代码图 7:人员端点
public interface PersonRepository extends JpaRepository<Person, Integer> {}
代码图 8:人员存储库
前端显示人物
在客户端,需要一个视图来显示人员数据,它使用Vadin 网格。所有 Vaadin 组件都是 Web 因此,组件可以很容易地与之相匹配 Lit 一起使用。Vaadin 网格提供了分页、排序等多种功能,使得以表格形式显示数据变得非常容易。
@customElement('person-view')export class PersonView extends View { @state() people: Person[] = []; async connectedCallback() { super.connectedCallback(); this.people = await PersonEndpoint.findAll(); } render() { return html` <vaadin-grid .items=${this.people} style="height: 100%"> <vaadin-grid-column path="firstName"></vaadin-grid-column> <vaadin-grid-column path="lastName"></vaadin-grid-column> <vaadin-grid-column path="email"></vaadin-grid-column> </vaadin-grid> `; }}
代码图 9:人物视图
在connectedCallback
将 Web 组件添加到 DOM 在时间调用的方法中,从终点读取人员实体(图 9)。添加了人员 Vaadin 在网格的项目属性中,“路径”属性用于定义人员属性的路径。为了简单起见,此示例不使用分页。如果表中包含大量记录,则应使用分页加载数据子集。HillaDataProvider
为此,它提供了当前显示的页面、页面大小、选择排序等信息,并在分页时逐页向终点请求数据。可以在GitHub 在存储库中找到详细的代码示例。
编辑人员
编辑数据需要创建表格。为此,使用了它 Vaadin Web 组件,如图 10 所示。
<vaadin-form-layout> <vaadin-text-field label="First name" ${field(this.binder.model.firstName)} ></vaadin-text-field> <vaadin-text-field label="Last name" ${field(this.binder.model.lastName)} ></vaadin-text-field> <vaadin-text-field label="Email" ${field(this.binder.model.email)} ></vaadin-text-field></vaadin-form-layout><vaadin-button @click=${this.save}>Save</vaadin-button>
代码图 10:表格
绑定实体Person
到组件,Hilla 提供一个活页夹(图) 11)。使用生成的活页夹。PersonModel
类别,包括相关性 Person 实体的附加信息,如验证或类型。
private binder = new Binder<Person, PersonModel>(this, PersonModel);
代码图 11:活页夹
为了保存更改的实体,我们使用了该方法 savePerson
扩展。PersonEndpoint
这种方法可以直接传递给binder。为此,单击事件绑定到按钮(见图片 10),并调用保存方法。保存后,重新加载此人的数据,更新网格(图 12)。
private async save() { await this.binder.submitTo(PersonEndpoint.save); this.people = await PersonEndpoint.findAll();}
代码图 12:保存方法
现在剩下的就是把选定的人从网格传递到活页夹。为此,可以使用 active-item-changed 事件(见图 13)。另外,需要通知网格选择了哪个人,这是用属性完成的selectedItems
。
<vaadin-grid .items=${this.people} @active-item-changed=${this.itemSelected} .selectedItems=${[this.selectedPerson]}>
代码图 13:网格选择
现在,在itemSelected
图 14 在方法中,只需从事件中读取选定的人并将其传递给活页夹。这将填写表格。
private async itemSelected(event: CustomEvent) { this.selectedPerson = event.detail.value as Person; this.binder.read(this.selectedPerson);}
代码图 14:itemSelected 方法
路由如果应用程序包含多个视图,我们将需要一种在视图之间导航的方法。为此,Hilla 使用 Vaadin 路由器(图 15)。hello-world-view
在这种情况下,导入应用程序启动时显示的视图, 。然后它被映射到根路径和路径hello-world
。在主视图的示例中,另一个视图延迟加载,因此只有在用户导航到它时才加载。最后,定义视图的布局,包括页眉、页脚和导航组件。
import {Route} from '@vaadin/router';import './views/helloworld/hello-world-view';import './views/main-layout'; export type ViewRoute = Route & { title?: string; icon?: string; icon?: string; children?: ViewRoute[];}; export const views: ViewRoute[] = [ { path: '', component: 'hello-world-view', icon: '', title: '', }, { path: 'hello-world', component: 'hello-world-view', icon: 'la la-globe', title: 'Hello World', }, { path: 'master-detail', component: 'master-detail-view', icon: 'la la-columns', title: 'Master-Detail', action: async (_context, _command) => { await import('./views/masterdetail/master-detail-view'); return; }, },];export const routes: ViewRoute[] = [ { path: '', component: 'main-layout', children: [...views], },];
代码图像:15 路由器配置
生产部署默认情况下,Hilla 在开发模式下运行应用程序配置。这需要更多的内存和内存 CPU 性能,但允许更容易调试。必须在生产模式下构建应用程序进行部署。在开发模式下,开发模式与生产模式的主要区别在于,Hilla 使用 Vite 将 JavaScript 文件传输到浏览器,而不是运行应用程序 Java 服务器。更改 JavaScript 或 CSS 考虑并自动部署更改文件。然而,在生产模式下,在施工过程中准备一次 JavaScript 和 CSS 使服务器能够更有效地处理所有请求。为了减少网络和浏览器的负载,可以进一步优化和最小化客户端资源。
Hilla 项目中的文件pom.xml
使用带有 Vaadin 在生产模式下创建构建插件配置的配置文件(图 16)。
<profiles> <profile> <id>production</id> <build> <plugins> <plugin> <groupId>dev.hilla</groupId> <artifactId>hilla-maven-plugin</artifactId> <version>${hilla.version}</version> <executions> <execution> <goals> <goal>build-frontend</goal> </goals> <phase>compile</phase> </execution> </executions> <configuration> <productionMode>true</productionMode> </configuration> </plugin> </plugins> </build> </profile></profiles>
代码图 16:Maven 插件
要创建生产建设,开发人员可以调用 Maven,如图 17 所示。这个过程将产生一个。 JAR 该文件包括可部署使用的所有依赖项和转换的前端资源。
./mvnw package -Pproduction
代码图 17:生产构建
结论由于 Hilla 与传统的单页应用程序开发相比,自动生成端点和模型类的访问代码,使前端和后端的集成更容易。包含的 Vaadin Web 组件(如网格)对数据密集型应用程序的开发也很有帮助。活页夹,尤其是和 Bean 验证结合使用,可以很容易地创建表单,并将代码降到最低。由于开发人员不需要处理前端构建和工具,Hilla 也非常适合 Java 开发人员。一般来说,这些特征是由这些特征造成的 Hilla 它可以与反应前端和反应前端相结合 Java 后端应用程序提供更高的效率。
这篇文章只涵盖了 Hilla 最关键的方面。Hilla 它提供了各种其他功能来创建功能齐全的应用程序,如风格和主题、安全、本地化、错误处理或应用程序范围的状态管理。官方文件涵盖了这些和许多其他主题。