雪浪OS前后端对接 - xuelang-group/suanpan-docs GitHub Wiki
修改项目代码,使得如下代码片段出现在前端打包后的 index.html 中。
<script>
window.appConfig = {url: '{{host}}', appId: '{{appId}}', nodeId: '{{nodeId}}'}
</script>
对于使用 ant design pro 的项目,修改的方法是在 document.ejs 中添加。
server.js 文件在使用 express 对外提供服务前,会依据算盘传入的命令行参数,替换 index.html 中的host, appId, nodeId 占位符。
前端使用的 Dockerfile 如下:
FROM registry.cn-shanghai.aliyuncs.com/shuzhi/base_express_server:1
WORKDIR /home/app/
COPY dist /home/app/dist
EXPOSE 7000
CMD tail -f /dev/null
使用的基础镜像为:registry.cn-shanghai.aliyuncs.com/shuzhi/base_express_server:1。
该镜像的代码可以参考:Base_Express_Server.zip
构建前端镜像的步骤如下:
- 编译前端项目源码,生成
dist
产物。 - 将 Dockerfile 与
dist
目录放置在同一个目录下 - docker build -f Dockerfile -t your_tag . (依据需求,替换your_tag)
构建完成后,可以将生成的镜像 push 到 Docker 镜像仓库,供设置算盘组件时使用。
前端通过 suanpan-sdk-js.min.js 中提供的 window.sp 对象,与后端在算盘上进行交互。
<script src="/common_public/dashboard/suanpan-sdk-js.min.js"></script>
window.spSocket = window.sp({
url: window.appConfig.url,
path: `/socket/${window.appConfig.appId}`
});
通过替换后的 url 以及 appId 生成 spSocket。
window.spSocket.subscribe({
eventName: `call-${window.appConfig.nodeId}`,
callback: function (data) {
console.log(data);
}
});
每当后端返回新消息,spSockert 的 subscribe 方法中 传入的 callback 就会被执行。
const userInstalledData = {
event: 'queryInstalledApps',
data: { id: '123' }
}
window.spSocket.send({
eventName: `call-${window.appConfig.nodeId}`,
data: {
success :true,
out1: JSON.stringify(userInstalledData),
}
});
spSocket 的 send 方法用于前端主动向后端传递消息。
例子中通过了一个 userInstalledData 对象,定义了与后台交互的信息格式。
- event:封装了前端期待后端完成的任务
- data:传递的数据
Java 后端使用 suanpan-java-sdk 对接算盘中基于 Redis stream 的消息队列。
suanpan-java-sdk 使用 Github 作为 maven 公网地址。
添加repo
<repositories>
<repository>
<id>RockingJavaBean-maven-master-repository</id>
<name>RockingJavaBean-maven-master-repository</name>
<url>https://raw.githubusercontent.com/RockingJavaBean/maven2/maven2/</url>
</repository>
...
</repositories>
添加依赖
<dependency>
<artifactId>com.xuelang</artifactId>
<groupId>suanpan-java-sdk</groupId>
<version>1.0.1</version>
</dependency>
使用 mvn 命令强制更新依赖
mvn clean
mvn package -U -Dmaven.test.skip=true
这是目前雪浪OS后端的代码,可以进行参考。
下面会先介绍一下代码中如何与前端进行交互。
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {
@Autowired
private GlobalEnv globalEnv;
@Autowired
private AliyunStoreOption aliyunStoreOption;
@Autowired
private StreamOption streamOption;
@Autowired
private MessageRecvHandler messageRecvHandler;
@Autowired
private UserAppService userAppService;
private void subscribeToMq() {
MqClient mqClient = streamOption.buildRedisClient();
Consumer consumer = Consumer.builder()
.queue(streamOption.getRecvQueue())
.group(streamOption.getNodeGroup())
.name(streamOption.getNodeId())
.delay(streamOption.getRecvQueueDelay())
.build();
log.info("subscribe queue: {}, group: {}, consumer: {}",
consumer.getQueue(), consumer.getGroup(), consumer.getName());
mqClient.subscribeQueue(
consumer,
this.messageRecvHandler,
new LogExceptionMessageHandler()
);
}
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
loggingInputOptions();
userAppService.syncInitialAppInformation();
log.info("app data synced to aliyun oss");
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future future = executorService.submit(this::subscribeToMq);
try {
future.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
executorService.shutdown();
}
private void loggingInputOptions() {
...
}
}
当程序完成启动时,subscribeToMq
方法会被执行,监听消息队列。
当有新消息发送过来时,subscribeToMq
会将封装好的消息数据交给 MessageRecvHandler
进行处理。
// com.xuelang.spos.mq.dto.MqEventDto
public class MqEventDto {
public static final String EMPTY_EVENT = "empty_event";
private String event = EMPTY_EVENT;
private JSONObject data;
}
MqEventDto
与 2.4 节中的 userInstalledData
对应,用于接收前端传入的数据。
该类中的 dispatchEvent
依据传入 event 类型,将数据分发给不同的业务类进行处理。
- 处理成功:使用
sendSuccessMessage
方法向队列发送成功信息,消息中包括了事件类型以及业务类返回的信息 - 捕获异常:使用
sendErrorMessage
方法向队列发送失败的消息
private void dispatchEvent(MqEventDto eventDto) {
MqClient mqClient = streamOption.buildRedisClient();
try {
switch (eventDto.getEvent()) {
case MqEventType.QUERY_INSTALLED_APP: {
String installedApp = aliyunStoreUserAppService.fetchInstalledAppContent();
sendSuccessMessage(mqClient, eventDto.getEvent(), installedApp);
break;
}
case MqEventType.QUERY_ALL_APP: {
String allApp = aliyunStoreUserAppService.fetchAllAppContent();
sendSuccessMessage(mqClient, eventDto.getEvent(), allApp);
break;
}
...
}
} catch (Exception e) {
log.error("dispatchEvent {} failed", eventDto.getEvent());
sendErrorMessage(mqClient, eventDto.getEvent());
} finally {
mqClient.destroy();
}
}
登陆算盘主页,在左侧菜单中选择 应用部署
,右键 我的项目
中的目录。
在弹出的对话框中选择 新建服务
。

输入服务名,点击确认。

点击全部组件上的 加号
按钮,选择服务组件。

接下来的步骤和配置服务组件相关,对于前端和后端组件会分别介绍。
- 代码类型: 选择 DashboardPage
- 自定义Docker镜像: 填入自己镜像的地址
- 自定义入口命令: node /home/app/server.js
- 第1操作:标签填写为“打开页面”,端口选择 7000 。

这里以 Java 后端为例。
- 代码类型: 选择 Runtime
- 自定义Docker镜像: 填入自己镜像的地址
- 自定义入口命令: java -jar /home/app/app.jar

其中 app.jar 为 Spring-boot 框架打包的产物,在构建 Docker 镜像的时候被放置在了 /home/app 目录下。
可以参考 spos-backend 项目中的 Dockerfile
,也可以跟据自己项目的构建配置进行修改。
对于 1-1 关系的前端/后端组件,请依据以下截图进行设置。

经过 0.2.3 的配置数据,组件已经可以相互连接。
请依据以下截图,将前端/后端组件的 输入1
与 输出1
连接起来

如果一个后端节点需要连接多个前端节点,除了要配置输入/输出数据,还需修改后端节点的接收方式
。

点击部署按钮,启动服务。
服务启动好后,组件的图标中会出现绿色的勾。

在页面的右侧菜单中,可以参看到组件启动日志。此外,对于前端应用,可以点击 打开界面
按钮,访问部署后的页面。
