在写这篇文章的时候 BGM 正好是这首歌,分享给你们。
javascript
项目截图java
前情摘要git
什么是 STOMP?
github
STOMP Simple or Streaming Text Orientated Messageing Protocal 是简单(流)文本定向传输协议。
web
STOMP 是 WebSocket 更高级的子协议,它使用一个基于帧的格式来定义消息,与 HTTP 的 Request 和 Response 相似。spring
STOMP 提供可互操做的链接格式,容许 STOMP 客户端与任意代理进行交互。STOMP 是一个很是简单易用的协议, 服务器端实现起来会相对困难一些,编写客户端很是容易。
typescript
STOMP over WebSocket
若是说 Socket 是 C/S 的TCP编程,同理 WebSocket 就是Web(B/S)的TCP编程,因此须要在客户端与服务端之间定义一个机制去协商一个子协议——更高级别的消息协议,将它使用在 WebSocket 之上去定义每次发送消息的类别、格式和内容,等等。shell
Angular 8 结合 ng2-stompjs
npm
本文的案例是实际的 Angular 8 项目中的一个功能模块(须要熟悉 Angular 和Typescript),模块主要包含由右键生成负责生产消息的 context-menu-component 动态组件,进度监控 app-progress-bar 组件和日志输出 app-console-area 组件。编程
...<nz-tab [nzType]="'card'"> <ng-template #consoleArea>控制台</ng-template> <app-progress-bar></app-progress-bar> <app-console-area></app-console-area> </div></nz-tab>...
代码与UI 视图的对应关系以下:
STOMP 客户端使用的是 ng2-stompjs 库, ng2-stompjs 目前的版本是 7.xx ,其底层的 @stomp / stompjs 已被重写,自此与 STOMP标准 具备严格的兼容性。
ng2-stompjs 是第一个可靠地支持二进制有效负载的 STOMP JS客户端库。
https://github.com/stomp-js/ng2-stompjs
$ npm install @stomp/ng-stompjs
添加和注入 @stomp/ng2-stompjs
import { InjectableRxStompConfig } from '@stomp/ng2-stompjs';import { STOMP_SERVER_BASE_URL } from 'server.config';const _window: any = window;
export const myRxStompConfig: InjectableRxStompConfig = { // Which server? brokerURL: _window.STOMP_SERVER_BASE_URL ? _window.STOMP_SERVER_BASE_URL : STOMP_SERVER_BASE_URL
// Headers // Typical keys: login, passcode, host connectHeaders: { login: 'guest', passcode: 'guest' },
// How often to heartbeat? // Interval in milliseconds, set to 0 to disable heartbeatIncoming: 0, // Typical value 0 - disabled heartbeatOutgoing: 20000, // Typical value 20000 - every 20 seconds
// Wait in milliseconds before attempting auto reconnect // Set to 0 to disable // Typical value 500 (500 milli seconds) reconnectDelay: 200,
// Will log diagnostics on console // It can be quite verbose, not recommended in production // Skip this key to stop logging to console debug: (msg: string): void => { console.log(new Date(), msg); }};
在建立实例时,此配置将由 Angular Dependency Injection 机制注入 RxStompService 服务,在 src/app/app.module.ts 文件中,添加如下内容。
import { InjectableRxStompConfig, RxStompService, rxStompServiceFactory } from '@stomp/ng2-stompjs';import { myRxStompConfig } from './config/stomp.config';...@NgModule({ [/* 声明模块内部成员的地方 */], : [/* 导入的其余module */], : [ : { provide: InjectableRxStompConfig, myRxStompConfig : }, { provide: RxStompService, rxStompServiceFactory, : [InjectableRxStompConfig] : } ], [/* 不会在模版中引用到的组件 */], : [AppComponent] : })
export class AppModule {}
创建链接
constructor(private rxStompService: RxStompService) { }
ngOnInit() { // 订阅 STOMP 消息 this.topicSubscription = this.rxStompService.watch('/topic/message').subscribe((message: Message) => { console.log(message.body); } this.errorSubscription = this.rxStompService.watch('/topic/error').subscribe((message: Message) => { this.progressInfo = message.body; });}
注:app-message-bar 组件默认是不显示的,当有消息传递进来时,此组件才会显示在页面中,进度达到 100% 时,会自动隐藏。
文章开头提到,STOMP 是一种基于帧的协议,其帧在 HTTP 上创建模型。一个框架由一个命令,一组可选的标题和一个可选的主体组成。

-
做为生产者,经过 SEND 框架将消息发送到服务器上的目的地。 做为消费者,发送 SUBSCRIBE 给定目的地的帧并从服务器接收消息做为MESSAGE 帧。
咱们的案例中两种模式同时存在,发送消息的是生产者(咱们上文提到的 context-menu-component 动态组件),接收消息的是消费者(app-progress-bar 组件)。消费者能够经过订阅不一样的 destination,来得到不一样的推送消息,不须要开发人员去管理这些订阅与推送目的地以前的关系。
接下来就介绍下做为生产者的 context-menu-component 组件,看看它都作了哪些事情吧。
context-menu-component 组件是触发右键时动态产生的组件,它负责经过向不一样的目的地 destination 下达不一样的指令,进而来实现不一样的功能需求。
// ts public openProjectManagerContextMenu(context: ProjectManagerContext): void { this.contextMenuComponent = this.nzDropdownService.create(context.mouseEvent, this.contextMenuTemplate);}
当咱们点击运行用例按钮时,它做为生产者会向 STOMP 服务端目的地 SEND 消息指令。
// 运行用例 public runProjectCases(): void { const streamTaskParam: StreamTaskParam = new StreamTaskParam(); streamTaskParam.project = this.globalService.projectInfo.projectName; this.openTaskProgressModal('/app/run-project-cases', JSON.stringify(streamTaskParam)); }
从代码得知,这会将消息发送到名为的 /app/run-project-cases 的目的地,STOMP 将此目标视为不透明字符串,而且目标名称不承担传递语义。
STOMP 定义了本身的消息传输体制。首先是经过一个后台绑定的链接点 endpoint来创建 socket 链接,而后生产者经过 SEND 方法,绑定好发送的目的地destination,而 topic 和 app 则是一种消息处理手段的分支,走 app/url 的消息会被你设置到的 MassageMapping 拦截到,进行你本身定义的具体逻辑处理,而走 topic/url 的消息就不会被拦截,直接到 Simplebroker 节点中将消息推送出去。(其中 simplebroker 是 spring 的一种基于内存的消息队列,你也可使用 activeMQ,rabbitMQ 代替)。
所以目的地 /app/run-project-cases 生产出来的消息会被拦截,最终会发送到消费者 app-progress-bar 组件 的 /topic/message。
接收消息
ngOnInit() { // 订阅 STOMP 消息 this.topicSubscription = this.rxStompService.watch('/topic/message').subscribe((message: Message) => { console.log(message.body); // do something }}
取消订阅
ngOnDestroy() { this.topicSubscription.unsubscribe();}
今天就介绍到这里吧,但愿你们多支持哦。
「框架篇」Hello Angular - 带你进入 Angular 世界
从观察者模式到迭代器模式系统讲解 RxJS Observable(一)
从观察者模式到迭代器模式系统讲解 RxJS Observable(二)
本文分享自微信公众号 - 像素摇摆(pxDance)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。