reactjs - 如何将 React webapp 集成到带有 jar 包装的 Spring Boot 应用程序中
问题描述
我们有一个 react webapp 和一个 spring boot 应用程序(用 maven 构建)正在开发中。
React 应用程序(在 npm 上)和引导应用程序是分开运行的,但现在是时候将它们集成起来并将其放入 QA/staging 中了。
我们正在使用 webpack 来捆绑 react 应用程序。
启动应用程序是一个带有 REST API(由反应前端消耗)的单个模块,具有用于数据库持久性的休眠。
问题
- react 和 boot 应用程序的目录结构应该是什么?我们想将整个应用程序(前端和后端)部署为 .jar(spring boot uberjar)
- 什么是反应应用程序开发工作流程?每次进行小的 css、html 或 .js 更改时,无需运行 maven 和运行 java -jar 的工作流程。
我在网络上找到了资源,其中反应和引导应用程序都位于单独的存储库/目录中,没有任何集成,这不是最佳的;我还没有找到一个资源,其中 webapp 资源和引导资源都在同一个目录树中,这也说明了开发生命周期和生产生命周期。
奖励:react 开发人员只知道 html/js/css。他们的 vscode/webstorm 项目中是否只有 react 应用程序资源?
解决方案
您可以在同一端口上运行 React 和 SpringBoot 并将它们打包为单个工件!请按照我在此处解释的步骤进行操作,这应该可以帮助您启动并运行。回答你的问题——
- 目录结构如下所示。两者都将位于同一根目录下。
- 关于 react 应用程序开发工作流程 - 您可以按照开发前端 react 项目的方式进行开发,使用热重载(保存文件,更改将自动反映)和有意义的错误消息。您将不得不使用代理进行通信。
这是我将在这里解释的演示项目的Github链接
Spring Boot 可以从src/main/resources/static
文件夹中提供静态内容。我们将利用 Spring Boot 的上述特性来服务于 react 项目的单页。我们将从目标目录中的静态文件夹中提供一个 html 页面,而不是在源目录中。
项目结构——
首先,使用https://start.spring.io创建一个 Spring Boot 项目。添加 Web 依赖项。将 groupId 和 artifactId 设置为您想要的任何内容。生成项目并将其解压缩到您的项目目录中。
或者,如果您使用的是 Spring Tools Suite,您只需单击
File->New->Spring Starter Project
并提及创建 Spring Boot 项目所需的详细信息。
里面的frontend
文件夹src/main
应该有你的 react 应用程序使用 create-react-app构建。
所以,有两个步骤-
- 创建前端的生产版本。
- 将生产版本复制到 ${target/classes/}。
我们将为此使用两个 maven 插件和Thymleaf。
对于第 1 步的 frontend-maven-plugin -如果您仔细查看pom.xml
那里,我已经提到了src
frontroy -maven-plugin将从中获取文件的目录,创建生产构建并将内容放在提到的输出目录中(内部src/main/frontend/build
)。
<workingDirectory>${frontend-src-dir}</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
对于步骤 2 中的 maven-resources-plugin -它将采用由frontend-maven-plugin刚刚创建的生产构建,然后将其放置在您的根目录target/classes/static
中。
然后我们将使用Thymleaftarget/classes/static
在控制器中使用 rest 端点提供静态内容。否则您必须输入 的名称html file
,例如http://localhost:8080/index.html
你的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.springreact</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Run React Frontend and SpringBoot Backend on the same port.</description>
<properties>
<java.version>1.8</java.version>
<frontend-src-dir>${project.basedir}/src/main/frontend</frontend-src-dir>
<node.version>v14.15.4</node.version>
<yarn.version>v1.16.0</yarn.version>
<frontend-maven-plugin.version>1.7.6</frontend-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<configuration>
<nodeVersion>${node.version}</nodeVersion>
<yarnVersion>${yarn.version}</yarnVersion>
<workingDirectory>${frontend-src-dir}</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
</configuration>
<executions>
<execution>
<id>install-frontend-tools</id>
<goals>
<goal>install-node-and-yarn</goal>
</goals>
</execution>
<execution>
<id>yarn-install</id>
<goals>
<goal>yarn</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>build-frontend</id>
<goals>
<goal>yarn</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<arguments>build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>position-react-build</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
<resources>
<resource>
<directory>${frontend-src-dir}/build</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
这是控制器代码。
package com.springreact.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class IndexController {
@GetMapping("")
public ModelAndView home() {
ModelAndView mav=new ModelAndView("index");
return mav;
}
}
如果你按照上面提到的步骤,你应该看到你的 React 应用程序正在启动http://localhost:8080/
。
有关更多详细信息,您可以查看我在上面写的博客。以下是两个不同平台上的博客链接-
推荐阅读
- apache-spark - 我们是否需要将 spark 二进制包上传到 http/s3/hdfs
- php - Moodle 上传文件问题 Uncaught DOMException: Blocked a frame with origin
- mongodb - Mongodb x.509'客户端没有可用的验证主题名称'
- python - python错误的日期递增
- javascript - 如何根据嵌套数组中的值过滤包含对象的数组并计算它们
- javascript - 文件输入自定义消息 HTML5 覆盖问题
- asp.net - 如何通过 ASP.NET 中的控制器在浏览器中打开 PDF 文件
- php - 使用 PHP ImageCreateFromJPEG() 不允许我重新创建图像:它生成一次并保存在服务器的缓存中,无论如何
- c++ - 打印以“a”开头的单词(在字符串中)
- sublimetext3 - Sublime Text 3 - 将默认“纯文本”设置为 HTML?