Spring stomp over websocket SubscribeMapping 不起作用

Posted

技术标签:

【中文标题】Spring stomp over websocket SubscribeMapping 不起作用【英文标题】:Spring stomp over websocket SubscribeMapping not working 【发布时间】:2018-07-16 22:01:47 【问题描述】:

我正在尝试在 Spring Boot 应用程序中为 stomp over websockets 配置订阅映射,但没有任何运气。我相当确定我已经正确配置了 stomp/websocket 的东西,因为我能够订阅由 kafka 消费者发布的主题,但是使用 @SubscribeMapping 根本不起作用。

这是我的控制器

@Controller
class TestController 
    @SubscribeMapping("/topic/test")
    fun testMapping(): String 
        return "THIS IS A TEST"
    

这是我的配置

@Configuration
@EnableWebSocketMessageBroker
@Order(Ordered.HIGHEST_PRECEDENCE + 99)
class WebSocketConfig : AbstractWebSocketMessageBrokerConfigurer() 

    override fun configureMessageBroker(config: MessageBrokerRegistry) 
        config.setApplicationDestinationPrefixes("/app", "/topic")
        config.enableSimpleBroker("/queue", "/topic")
        config.setUserDestinationPrefix("/user")
    

    override fun registerStompEndpoints(registry:StompEndpointRegistry) 
        registry.addEndpoint("/ws").setAllowedOrigins("*")
    

    override fun configureClientInboundChannel(registration: ChannelRegistration?) 
        registration?.setInterceptors(object: ChannelInterceptorAdapter() 
            override fun preSend(message: Message<*>, channel: MessageChannel): Message<*> 
                val accessor: StompHeaderAccessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor::class.java)
                if (StompCommand.CONNECT.equals(accessor.command)) 
                    Optional.ofNullable(accessor.getNativeHeader("authorization")).ifPresent 
                        val token = it[0]
                        val keyReader = KeyReader()
                        val creds = Jwts.parser().setSigningKey(keyReader.key).parseClaimsJws(token).body
                        val groups = creds.get("groups", List::class.java)
                        val authorities = groups.map  SimpleGrantedAuthority(it as String) 
                        val authResult = UsernamePasswordAuthenticationToken(creds.subject, token, authorities)
                        SecurityContextHolder.getContext().authentication = authResult
                        accessor.user = authResult
                    
                
                return message
            
        )
    

然后在 UI 代码中,我使用带有 stompjs 包装器的 angular 来订阅它,如下所示:

this.stompService.subscribe('/topic/test')
      .map(data => data.body)
      .subscribe(data => console.log(data));

像这样订阅我知道正在发出数据的主题非常有效,但订阅映射什么也不做。我还尝试在我的 websocket 配置中添加一个事件侦听器,以测试 UI 是否实际上正在向后端发送订阅事件,如下所示:

    @EventListener
    fun handleSubscribeEvent(event: SessionSubscribeEvent) 
        println("Subscription event: $event")
    

    @EventListener
    fun handleConnectEvent(event: SessionConnectEvent) 
        println("Connection event: $event")
    

    @EventListener
    fun handleDisconnectEvent(event: SessionDisconnectEvent) 
        println("Disconnection event: $event")
    

添加这些事件侦听器后,我可以看到我期望从 UI 获得的所有事件都在 kotlin 层中通过,但我的控制器方法从未被调用。我有什么明显的遗漏吗?

【问题讨论】:

【参考方案1】:

尝试以下方法:

@Controller
class TestController 

    @SubscribeMapping("/test")
    fun testMapping(): String 
        return "THIS IS A TEST"
    

【讨论】:

你是救生员,谢谢。我不知道为什么这有效。我昨天一整天都在尝试不同的变化。我认为我遇到的问题是我尝试过的控制器最初有一个 RestController 注释。我猜您不能将 Get/Put/Post 映射与 SubscribeMapping 混合使用。看到 intellij 在那个断点处停止让我早上起来。 /topic 将被隐式添加到您提供的 URL 中。很高兴我做了你的早晨:)

以上是关于Spring stomp over websocket SubscribeMapping 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

SockJS over stomp 使用 angular2 和 spring boot

Spring with STOMP over SockJS 和 Tomcat 未升级到 Websockets

Spring Boot + Stomp over WS 与嵌入式 Artemis 代理“目标不存在”

STOMP over websockets 与普通 STOMP。哪一个更好?

RabbitMQ Stomp over websocket:无法检索排队的消息

春天的 websocket stomp over sockjs 重定向到 http 协议,而在关键的 web 服务中起源是 https