Spring Boot中的多播Websockets

Jor*_*kie 8 java authentication spring websocket spring-boot

上下文

第一次在春天使用websockets.我的应用程序涉及一种类型的用户(CHAP)将其当前位置提供给订阅的所有其他人(USR)(并且有权订阅此信息)

我正在阅读文档并找到了我认为可以解决这个问题的这一部分,但我并不是百分之百确定它是如何工作的,并且会喜欢有更强理解力的人换句话说.我已经看到类似的堆栈溢出问题,但解决方案感觉太具体(虽然这可能只是我自己缺乏理解).

问题

每个主题一个CHAP,可以将其位置发布到主题.用户可以订阅其授权订阅的任何主题.

基本上:

  • 变量端点上的多个主题(类似于/ {route_id}/location)

  • 用户可以订阅这些主题并在可用时接收更新

  • 具有CHAP角色的用户可以发布到一个主题.(即每个CHAP都有一个可以发布到的{route_id}.

  • 具有USR角色的用户可以收听他们所属的多个主题(即每个USR都有几条路线可以监听更新)

这与具有多个聊天室的问题类似,这是websockets的常见示例.但是我找到的所有示例都有静态聊天室名称,单个聊天室,或者只能将消息定位到一个用户(不是一个组)

现行守则

@MessageMapping("/chaperone/location") // chaperone sends data to here
@SendTo("/{route_id}/location") // users can listen in on this
public BusModel updateLocation(@DestinationVariable long route_id, BusModel busModel) {
    return routeService.updateBusLocation(busModel);
}
Run Code Online (Sandbox Code Playgroud)

我的想法是,伴侣发布到该URL,所有订阅他们路线的用户都会得到更新.

谢谢!

Jor*_*kie 2

事实证明这是一个解决方案,并且不需要像我之前想象的那样进行太多配置。这是我的版本:

WebSocket配置

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    public static final String TOPIC="/topic";

    /**
     * Consumers connect to endpoint/live to connect to the websocket
     *
     * @param registry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/live").setAllowedOrigins("*").withSockJS();
    }

    /**
     * Once connected to the websocket, users can subscribe to endpoints prefixed with /topic
     * as these are managed by the message broker.
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker(TOPIC);
        registry.setApplicationDestinationPrefixes("/");
    }
}
Run Code Online (Sandbox Code Playgroud)

现场控制器

@SubscribeMapping(TOPIC + "/routes/{route_id}")
public MessageWrapper subscribeToRouteLocation(
        @DestinationVariable(value = "route_id") long route_id) {
    LOG.debug("New user subscribed to location of route %d", route_id);
    return new MessageWrapper(LOCATION_MESSAGE, routeService.getBusForRoute(route_id));
}

@MessageMapping("/routes/{route_id}")
@SendTo(TOPIC + "/routes/{route_id}")
public MessageWrapper updateRouteLocation(
        @DestinationVariable(value = "route_id") long route_id,
        @Payload BusStatusUpdateModel busLocation) {
    if (busLocation.getLat() == 0 && busLocation.getLon() == 0) {
        LOG.debug("Ending route %d", route_id);
        return new MessageWrapper(ROUTE_TERMINATED_MESSAGE, routeService.endBusForRoute(route_id));
    } else {
        LOG.debug("Updating location of route %d", route_id);
        BusStatusUpdateModel statusUpdateModel = routeService.updateBusLocation(busLocation, route_id);
        return new MessageWrapper(LOCATION_MESSAGE, statusUpdateModel);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此发送到 /routes/{route_id} 的消息将被传递给 /topic/routes/{route_id} 的订阅者

我还没有测试授权的东西,一旦我得到它就会填写!