在寫這篇文章的時候 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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。