簡體   English   中英

帶有Spring的多個私有WebSocket消息

[英]Multiple Private WebSocket Messages with Spring

我正在使用Spring @RequestMapping來使用和生成JSON的REST同步服務。 現在,我想添加異步響應,即客戶端發送ID列表,服務器將詳細信息發送回去,因為它將詳細信息發送給一個客戶端。

我搜索了一段時間,沒有找到我想要的東西。 我已經看到了Spring的兩種不同方法。 最常見的是消息代理方法,其中似乎每個人都通過訂閱隊列或主題來獲取每條消息。 因為這是私人數據,所以這是非常不可接受的。 我也有有限數量的數據點要返回。 另一種方法是Callable,AsyncResult或DeferredResult。 這似乎使數據保密,但是我想發送多個響應。

我已經看到了與我想要的東西類似的東西,但是在服務器上使用了Jersey SSE 我想堅持使用Spring。

這是我目前使用偽代碼的方式。

@RequestMapping(value = BASE_PATH + "/balances", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public GetAccountBalancesResponse getAccountBalances(@RequestBody GetAccountBalancesRequest request) {
  GetAccountBalancesResponse ret = new GetAccountBalancesResponse();

  ret.setBalances(synchronousService.getBalances(request.getIds());

  return ret;
}

這就是我想要做的。 因為我不了解細節,所以這很粗糙。 一旦確定發送,我將致力於異步部分,但會提出任何建議。

@RequestMapping(value = BASE_PATH + "/balances", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ???<BalanceDetails> getAccountBalances(@RequestBody GetAccountBalancesRequest request) {
  final ???<BalanceDetails> ret = new ???<>();

  new Thread(new Runnable() {
    public void run() {
      List<Future<BalanceDetails>> futures = asynchronousService.getBalances(request.getIds());

      while(!stillWaiting(futures)) {
        // Probably use something like a Condition to block until there is some details.
        ret.send(getFinishedDetails(futures));
      }

      ret.close();
    }
  }).start();

  return ret;
}

謝謝,韋斯。

它不是這樣工作的:您使用的是普通的Spring操作,這些操作旨在在possilby阻塞的單個線程中進行處理,直到計算出完整的請求為止。 您不會在控制器內部創建線程-或至少不會以這種方式創建線程。

如果計算持續很長時間,並且您想為用戶提供視覺反饋,請執行以下步驟:

  • 優化程序:)使用索引,緩存等
  • 如果還不夠,計算仍然會永遠持續下去,並且用戶需要反饋,您將有兩種選擇

    • 使用javascript輪詢並顯示視覺反饋(更輕松)。 基本上,您將任務提交到線程池中並立即返回,還有另一個控制器方法可讀取計算的當前狀態並將其返回給用戶。 javascript每10秒左右調用一次此方法
    • 使用反向通道(服務器推送, websocket )-並不是那么容易,因為您必須同時實現客戶端和服務器部分。 顯然,有一些庫和協議可以使這幾行代碼變得很長,但是如果您以前從未嘗試過,則需要花一些時間來了解安裝過程-而且調試Websockets不如常規HTTP容易,因為調試工具

進行了大量的挖掘工作,但看起來Spring Web 4.2確實支持服務器端事件。 我正在使用使用Spring Web 4.1.7的Spring Boot 1.2.7。 切換到Spring Boot 1.3.0.RC1將添加SseEmitter。

這是我的偽代碼。

@RequestMapping(value = BASE_PATH + "/getAccountBalances", method = RequestMethod.GET)
public SseEmitter getAccountBalances(@QueryParam("accountId") Integer[] accountIds) {
  final SseEmitter emitter = new SseEmitter();

  new Thread(new Runnable() {

    @Override
    public void run() {
      try {
        for (int xx = 0; xx < ids.length; xx++) {
          Thread.sleep(2000L + rand.nextInt(2000));

          BalanceDetails balance = new BalanceDetails();
          ...
          emitter.send(emitter.event().name("accountBalance").id(String.valueOf(accountIds[xx]))
                  .data(balance, MediaType.APPLICATION_JSON));
        }

        emitter.send(SseEmitter.event().name("complete").data("complete"));
        emitter.complete();
      } catch (Exception ee) {
        ee.printStackTrace();
        emitter.completeWithError(ee);
      }
    }
  }).start();

  return emitter;
}

仍然可以正常關閉通道並使用Jersey EventSource解析JSON對象,但是它比消息總線要好得多。

此外,生成新線程並使用睡眠僅適用於POC。 我也不需要,因為我們已經有一個異步過程來訪問緩慢的后端系統。

韋斯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM