容器化和分布式Quarkus应用程序的一个常见模式是作为一个独立的前端应用程序的高效和可扩展的后端。 在Kubernetes世界中,前端应用程序可以是一个纯粹的Web层pod,如React、Angular或Vue.js,将所有REST调用委托给这些Quarkus服务层pod。

虽然这种方法有独立的容器扩展和独立的生命周期的好处,但对于小型应用来说,有时可能是过度设计了。
也许你只是想创建一个小型的独立CRUD应用,而不影响现代的Web GUI技术? 我们已经看到了如何用Angular来实现这一点,但是React呢,至少根据GitHub上的星星已经超过了Angular的流行程度? 这一切都与选择有关,我将向你展示你如何不仅可以整合React,还可以使用一个名为Patternfly的Web组件框架。 Patternfly是一个模式、组件和风格的集合,用于创建丰富、一致和互动的GUI。
让我们创建一个带有REST端点的Quarkus应用程序,为原子粒子对象提供服务,并在React/Patternfly表中显示。 最终应用程序的源代码可以在这里找到。
第1步 - 生成Quarkus项目
要生成一个启动项目,请访问code.quarkus.io。在Maven组中输入 "io.quarkus",在Artifact中输入 "quarkus-react"。 在扩展列表中选择RESTEasy JAX-RS和RESTEasy JSON-B。然后生成并下载项目,在本地机器上解压,在你喜欢的IDE中打开项目文件夹。
第2步 - 添加Quarkus REST端点
在样本GreetingResource.java所在的Java包文件夹/src/main/java/io/quarkus中,创建一个名为Particle.java的新bean类,内容如下。
package io.quarkus;
public class Particle {
private String name;
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
}
现在创建一个新的REST资源类,名为ParticleResource.java,在这里我们返回一些测试粒子(这里忽略了任何原子物理学的影响)。
package io.quarkus;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("/particles")
public class ParticleResource {
@GET
public Set<Particle> getUsers() {
Set <Particle> particleList = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
Particle particle = new Particle();
particle.setName("Graviton");
particleList.add(particle);
Particle particle2 = new Particle();
particle2.setName("Pentaquark");
particleList.add(particle2);
return particleList;
}
}
通过在开发模式下启动Quarkus来测试一切是否正常。
在一个新的终端中调用端点来查看你的粒子响应。
$ curl http://localhost:8080/particles
[{"name":"Graviton"},{"name":"Pentaquark"}]
我们的Quarkus数据层现在已经准备好了,所以接下来让我们创建React GUI。
第3步 - 生成React项目
确保你已经在你的系统上安装了Node.js和npm。 如果需要,请参考官方文档以获得更多信息。
在你的项目中创建一个新的文件夹/src/main/webapp,这将是你React项目的基础文件夹。现在在这个文件夹中打开另一个终端,运行React项目初始化程序,然后添加Patternfly节点模块。
$ npx create-react-app .
$ npm install @patternfly/patternfly --save
| 当启动React应用程序时,它将默认在3000端口运行。当我们试图访问8080端口的Quarkus端点时,由于CORS安全策略,浏览器会阻止它。 在生产中,这并不重要,因为编译好的静态React应用也会通过8080端口从Quarkus提供服务,但在开发过程中这是一个问题。 |
幸运的是,React有一个整洁的小功能,叫做代理,它可以将所有未知端点的请求转发到另一个URL。在/webapp文件夹中,打开package.json文件,添加代理行,将所有请求转发到我们的Quarkus端口8080上。
{
"name": "webapp",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.3",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:8080/",
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
第4步 - 创建一个Patternnfly表组件来填充我们的数据
在React项目的/webapp/src/index.js中导入Patternfly的CSS。
...
import './index.css';
import '@patternfly/patternfly/patternfly.css';
import App from './App';
...
在/webapp/src中创建一个新的文件夹,名为components,在里面创建一个名为particles.js的文件,通过循环播放粒子对象的列表来生成一个 Patternfly 表格。
import React from 'react'
const Particles = ({ particles }) => {
return (
<div>
<center><h1>Particles List</h1></center>
<table class="pf-c-table pf-m-grid-md" role="grid" aria-label="Supersonic Subatomic Particles" id="table-basic">
<caption>Supersonic Subatomic Particles</caption>
<thead>
<tr role="row">
<th role="columnheader" scope="col">Name</th>
</tr>
</thead>
{particles.map((particle) => (
<tbody role="rowgroup">
<tr role="row">
<td role="cell" data-label="Particle name">{particle.name}</td>
</tr>
</tbody>
))}
</table>
</div>
)
};
export default Particles
接下来调整/webapp/src/App.js,调用我们的Quarkus服务端点,用响应数据渲染我们的粒子组件。
import React, {Component} from 'react';
import Particles from './components/particles'
class App extends Component {
state = {
particles: []
}
componentDidMount() {
fetch('/particles')
.then(res => res.json())
.then((data) => {
this.setState({ particles: data })
})
.catch(console.log)
}
render () {
return (
<Particles particles={this.state.particles} />
);
}
}
export default App;
我们现在准备在React开发模式下测试我们的GUI, 确保Quarkus仍在另一个终端中运行
在/webapp文件夹中执行 :
一个浏览器将打开到http://localhost:3000。 如果没有的话,请导航到该URL。 你应该看到我们的表格从你的Quarkus粒子后台动态地填充出来。 在浏览器的开发者工具中,你会看到数据实际上是从http://localhost:3000/particles。

我们现在是在双重开发模式下运行。对你的Java或Javascript代码所做的任何修改都将被立即应用。 这不是开发者的幸福吗?
但你问的容器化部署是怎么回事?好吧,一旦你闪亮的新GUI应用准备好了,我们还需要做一些最后的调整来构建可运行的jars和image。
第5步 - 为生产构建准备我们的项目
在**/webapp/package.json**中添加一个prod build阶段。
...
"eject": "react-scripts eject",
"prod": "react-scripts build --dest && rsync -a build/* ../resources/META-INF/resources"
},
"proxy": "http://localhost:8080/",
...
这将对静态React资产进行生产构建,并将其复制到静态文件的默认Quarkus目录中。
| rsync命令是针对Linux的。 对于其他操作系统,请用一个同等的命令来代替。 |
最后一步,我们将在pom.xml中添加优秀的frontend-maven-plugin,它将从普通的maven构建中触发这些React构建阶段。调整npm和node的版本,使其与你本地安装的版本相匹配。maven安装阶段实际上会安装这两个包,这对CI/CD构建或开始使用该项目时很方便。
<build>
...
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.11.2</version>
<configuration>
<workingDirectory>${project.basedir}/src/main/webapp</workingDirectory>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v14.15.4</nodeVersion>
<npmVersion>6.14.10</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run prod</arguments>
</configuration>
</execution>
</executions>
</plugin>
</build>
现在我们来构建可运行的jar。
停止所有其他运行环境以释放端口并运行。
$ java -jar target/quarkus-app/quarkus-run.jar
打开你的浏览器到http://localhost:8080,再次看到你的表格,现在从一个优化的Quarkus jar中运行。
收获
这就是你的收获。只需几个简单的步骤,你就可以使用React和Patternfly的力量来为你的Quarkus应用添加漂亮的交互式图形用户界面。
接下来把这个应用编译成本地的,以部署一个非常轻量级的webapp怎么样?或者你可能想看看其他Patternfly组件来创建一个更复杂的网络界面。无论哪种方式,除了你的创造力之外,没有任何界限可以让你的Quarkus应用程序大放异彩。