使用 React 和 Vert.x 进行单页应用程序开发

本文档将向您展示如何使用 React 和 Vert.x 开发单页应用程序 (SPA)。

您将构建什么

您将创建一个 React 前端,并通过 HTTP 与 Vert.x 后端进行通信。

开发工作流程

开发 SPA 时,更新 Javascript、HTML 或 CSS 文件后能获得即时反馈非常方便。使用 React,这需要您使用 npm 启动一个开发服务器,处理前端资源请求

Frontend resource

但是,必须由 Vert.x 处理的请求怎么办?您将配置项目,以便前端开发服务器将 API 请求代理到后端

API request

您需要什么

  • 文本编辑器或 IDE

  • Java 11 或更高版本

  • Maven 或 Gradle

  • Node

  • npm

  • npx,一个 NPM 包运行器

创建项目

此项目的代码包含功能等效的 Maven 和 Gradle 构建文件。

使用 Maven

在您的 Maven POM 文件中添加 vertx-web 依赖

Maven pom.xml
  <dependencies>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-web</artifactId>
      <version>${vertx.version}</version>
    </dependency>
  </dependencies>

然后添加 exec-maven-plugin

Maven pom.xml
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.5.0</version>
        <configuration>
          <mainClass>io.vertx.howtos.react.BackendVerticle</mainClass>
        </configuration>
      </plugin>

使用 Gradle

假设您使用带有 Kotlin DSL 的 Gradle,请添加 vertx-web 依赖

Gradle build.gradle.kts
dependencies {
  val vertxVersion = "5.0.0.CR2"
  implementation("io.vertx:vertx-web:${vertxVersion}")
}

然后配置应用程序主类

Gradle build.gradle.kts
application {
  mainClass = "io.vertx.howtos.react.BackendVerticle"
}

通过 HTTP 暴露消息服务

让我们从后端服务开始。它将通过返回一条问候消息来处理 /api/message 路径上的请求

Java src/main/java/io/vertx/howtos/react/BackendVerticle.java
    Router router = Router.router(vertx);
    Route messageRoute = router.get("/api/message"); // (1)
    messageRoute.handler(rc -> {
      rc.response().end("Hello React from Vert.x!"); // (2)
    });

    router.get().handler(StaticHandler.create()); // (3)

    return vertx.createHttpServer()
      .requestHandler(router)
      .listen(8080);
  1. 定义了一个 Vert.x Web Route,用于匹配 /api/message 路径上的 HTTP 请求

  2. Route 处理程序用问候消息回复请求

  3. 需要 StaticHandler 来处理静态资源请求

重要
您可能想知道如果前端开发服务器处理静态资源,为什么我们还需要 StaticHandler?请记住,当整个应用程序构建并投入生产时,前端将与后端 HTTP 服务器捆绑在一起并由其提供服务。

在我们测试实现之前,BackendVerticle 需要一个 main 方法

Java src/main/java/io/vertx/howtos/react/BackendVerticle.java
  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx(); // (1)
    vertx.deployVerticle(new BackendVerticle()).await(); // (2)
    System.out.println("Verticle started!");
  }
  1. 创建一个 Vertx 上下文

  2. 部署 BackendVerticle

您可以运行该应用程序

  • 直接从您的 IDE 运行,或者

  • 使用 Maven:mvn compile exec:java,或者

  • 使用 Gradle:./gradlew run (Linux, macOS) 或 gradlew run (Windows)。

注意
以下示例使用 HTTPie 命令行 HTTP 客户端。如果您的系统尚未安装它,请参阅安装文档。

要收到问候语,请打开您的终端并执行此命令

http :8080/api/message

您应该会看到

HTTP/1.1 200 OK
content-length: 24

Hello React from Vert.x!

在浏览器中显示消息

我们有一个完全可用的后端,我们可以创建前端。为此,请使用 npx 运行 create-react-app

cd src/main
npx create-react-app frontend

这将

  • 创建一个 package.json 文件,其中定义了依赖项以及构建和运行脚本

  • 安装依赖项

  • 生成一个骨架应用程序

注意
在本操作指南中,前端代码作为后端项目的一部分,位于 src 目录内。这更容易上手,特别是如果您的团队包含更多偏向后端的开发人员。但是,随着您的项目增长,您可能更喜欢将前端和后端拆分为单独的模块。

骨架应用程序在这里不是重点,所以我们将其删除

rm -rf frontend/src/*

然后打开您喜欢的编辑器并实现 React 前端

Javascript src/main/frontend/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';

class Greeter extends React.Component { // (1)

  constructor(props) {
    super(props);
    this.state = { // (2)
      message: "Default message"
    }
  }

  componentDidMount() { // (5)
    fetch("/api/message")
      .then(response => response.text())
      .then(text => this.setState({message: text}));
  }

  render() { // (3)
    return (
      <div>
        <span>{this.state.message}</span>
      </div>
    );
  }
}

ReactDOM.render( // (4)
  <Greeter/>,
  document.getElementById('root')
);
  1. 我们的前端包含一个简单的 React Greeter 组件

  2. Greeter 组件持有状态,这是一个要在浏览器中显示的消息

  3. 消息显示在一个简单的 HTML span

  4. Greeter 组件在网页中渲染

  5. 初始渲染后,一个 HTTP 请求被发送到后端;结果用于更新组件状态

最后但同样重要的是,您必须配置前端开发服务器以将 API 请求代理到后端。在您的编辑器中打开 package.json 文件并添加

Javascript src/main/frontend/package.json
"proxy": "https://:8080"

就是这样,打开一个终端并启动前端开发服务器

cd src/main/frontend
npm start

应该会自动打开一个浏览器选项卡并指向 https://:3000

您应该会看到

Hello React from Vert.x!

整合所有内容

当然,在生产环境中您将不会启动前端开发服务器。因此,Maven POM(或 Gradle 构建)文件应配置为

  • 运行前端构建

  • 将静态文件复制到 src/main/resources/webroot 文件夹

注意
您还记得第一节中的 StaticHandler 吗?它默认在 webroot 文件夹中查找静态文件。这就是为什么您必须将静态文件复制到 src/main/resources/webroot

将这些插件添加到您的 Maven POM 文件

Maven pom.xml
      <plugin>
        <groupId>com.github.eirslett</groupId>
        <artifactId>frontend-maven-plugin</artifactId>
        <version>1.7.6</version>
        <configuration>
          <nodeVersion>v22.12.0</nodeVersion>
          <npmVersion>10.9.0</npmVersion>
          <workingDirectory>src/main/frontend</workingDirectory>
          <installDirectory>target</installDirectory>
        </configuration>
        <executions>
          <execution>
            <id>install-node-and-npm</id>
            <phase>generate-resources</phase>
            <goals>
              <goal>install-node-and-npm</goal> <!--(1)-->
            </goals>
          </execution>
          <execution>
            <phase>generate-resources</phase>
            <id>npm-install</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <configuration>
              <arguments>install</arguments> <!--(2)-->
            </configuration>
          </execution>
          <execution>
            <id>npm-run-build</id>
            <phase>generate-resources</phase>
            <goals>
              <goal>npm</goal> <!--(3)-->
            </goals>
            <configuration>
              <arguments>run build</arguments>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.1.0</version>
        <executions>
          <execution>
            <id>copy-to-webroot</id>
            <phase>process-resources</phase>
            <goals>
              <goal>copy-resources</goal> <!--(4)-->
            </goals>
            <configuration>
              <outputDirectory>${project.build.outputDirectory}/webroot</outputDirectory>
              <resources>
                <resource>
                  <directory>${basedir}/src/main/frontend/build</directory>
                  <filtering>false</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
  1. 在构建目录中下载 Node 和 npm 可以在 CI 上运行前端构建,即使这些环境中可能没有它们

  2. 使用 npm install 下载前端依赖项

  3. 创建前端的生产就绪构建

  4. 将静态文件复制到 src/main/resources/webroot

如果您使用 Gradle,请首先添加 Gradle NPM 插件

Gradle build.gradle.kts
import com.github.gradle.node.npm.task.NpmTask

plugins {
  java
  application
  id("com.github.node-gradle.node") version "7.0.2"
}

那么配置类似于我们使用 Maven 所做的

Gradle build.gradle.kts
node {
  version = "22.12.0"
  npmVersion = "10.9.0"
  download = true
  nodeProjectDir = File("src/main/frontend")
}

val buildFrontend by tasks.creating(NpmTask::class) {
  args = listOf("run", "build")
  dependsOn("npm_install")
}

val copyToWebRoot by tasks.creating(Copy::class) {
  from("src/main/frontend/build")
  destinationDir = File("build/classes/java/main/webroot")
  dependsOn(buildFrontend)
}

val processResources by tasks.getting(ProcessResources::class) {
  dependsOn(copyToWebRoot)
}

确保所有之前的 npmmvngradlew 执行都已终止,然后启动 Vert.x 服务器

  • 使用 Maven:mvn compile exec:java,或者

  • 使用 Gradle:./gradlew run (Linux, macOS) 或 gradlew run (Windows)。

浏览到 https://:8080,您应该会看到

Hello React from Vert.x!

总结

本文档涵盖了

  1. 使用 create-react-app 创建一个新的 React 应用程序

  2. 运行一个前端开发服务器(用于实时重载),将 API 请求委托给 Vert.x 后端

  3. 在投入生产时将前端静态文件与 Vert.x 类一起捆绑


最后发布:2025-02-03 01:47:34 +0000。