34

我想将状态同步到对特定实体更改感兴趣的所有客户。所以我想实现类似的目标:

  • 在实体上公开 CRUD API(通过HTTP/RESTwebsockets
  • 并将(修改调用的)响应路由到websockets主题

所以从技术上讲,我会对将spring-data-restspring websockets 实现混合以实现类似 spring-data-websocket 的想法感兴趣。

我想到了两种解决方案,实际上两者都是:

  • spring-data-rest 通过暴露我的实体REST/HTTP API
  • websocket控制器(用于实体的修改调用)

websocket控制器看起来像这样:

@Controller
public class EntityAWebSocketController {
      @MessageMapping("/EntityA/update")
      @SendTo("/topic/EntityA/update")
      public EntityA update(EntityA entityA) throws Exception {
           // persist,....
           return entityA;
     }
}

场景一:Websocket API调用自REST/HTTP API

规则:

  • 客户请求总是REST/HTTP API
  • 响应REST/HTTP API适用于所有操作
  • 此外,对于修改操作,websocket消息也会出现

从技术上讲,可以通过以下方式实现:

  • 从spring-rest-data 事件中调用websocket控制器(即在, , , 中)AfterCreateEventAfterSaveEventAfterLinkSaveEventAfterDeleteEvent

解决方案对我来说似乎还是很恶心,因为我需要这样做:

  1. 客户端 A --HTTP请求 --> 服务器(spring-data-rest 控制器)
  2. 服务器(spring-data-rest 控制器中的AfterXXXEvent)--websocket消息--> Springwebsocket控制器
  3. Spring websocket 控制器——websocket通过主题发送消息——>所有对主题感兴趣的客户端
  4. 服务器(spring-data-rest 控制器)--HTTP响应--> 客户端 A

场景2:Websocket API独立于REST API

规则:

  • 客户端请求仅REST/HTTP API用于非修改操作
  • 响应仅REST/HTTP API用于非修改操作
  • websocket客户端为所有修改操作发送消息
  • websocket仅针对所有修改操作向客户端发送消息

好吧,如果没有其他想法出现,我会选择后一个,但是,如果我也能以某种方式生成C(R)UD通过websockets类似 spring-data-websockets 的方法公开并且只处理我的实现。

因为我觉得我必须手动公开(通过*WebSocketControllers)CUD我所有实体的所有方法。我可能太懒了。

想法?

4

2 回答 2

1

方案 2 在最后一步中谈到了一个客户。但我认为您的要求是针对一个主题,因为您需要多个客户。如果我想根据您的要求完成 2,那么您可能需要维护一个客户端列表并实现您自己的队列,或者使用 ForkJoinPool 向所有在您的 WebSocket 上侦听的客户端发送消息。话虽如此,A 主题在这里肯定更优雅,但整体看起来太复杂了不同的界面

对于从客户端到服务器的所有消息,只需使用简单的有线协议并使用集合来参数化,它可以是 RParam1.......

在服务器上,您需要一个控制器将这些映射到不同的请求(和操作)。不知何故,看起来工作量不大。希望这可以帮助。

于 2015-06-21T17:33:01.877 回答
0

相同的架构已经困扰了我一段时间,如果我想提及它的所有缺点和优点,那将是一个很长的故事,所以让我进入实现。

第二种情况是有效的,但正如您所提到的,最好在同一个 websocket 会话上执行 crud 操作。这将消除对每个请求的 HTTP 握手的需要,并减少消息的主体大小,因此您将有更好的延迟。同时,您已经与服务器建立了持久连接,那么为什么不好好利用它呢?

我搜索了一段时间,在您提出问题 6 年后,我仍然找不到任何可以实现这一点的 websocket 协议,所以我决定自己解决这个问题,因为我需要它用于另一个虚拟项目。

这种协议的另一个优点可能是它不需要对您已经编写的控制器进行太多更改。所以它应该能够支持 Spring Framework(例如)注释并从中制作 websocket 端点。在另一个框架(如 spring)中实现此类协议的难点在于,创建 ServletRequest 和 ServletResponse 并将它们转换为您自己的 websocket 协议并不好,您会失去一些优势。例如,到目前为止,您在应用程序中编写的任何 http 过滤器都将毫无意义,因为通过这些过滤器传递 websocket 消息并不容易。

关于协议本身:我决定通过 json 格式传递所有内容,以及每个请求的唯一 ID,以便我们可以将客户端的回调映射到请求 ID。当然,还有一个过滤器链可以将您的过滤器添加到其中。

这里另一个难以处理的事情是 Spring Security,因为在某些情况下它也像 http 过滤器一样工作。在我自己的库中,我终于可以处理注释,@PreAuthorize但如果您antMatchers在 HTTP 安全配置中使用,那将是一个问题。

因此,创建 websocket 适配器来调用 http 控制器会有很多弊端。

您可以在此处查看该项目:Rest Over Websocket。它是为 Spring Boot 编写的。

于 2020-08-14T07:45:23.287 回答