SimpMessagingTemplate 未在 spring 启动时发送消息

SimpMessagingTemplate not sending messages in spring boot

大家好,我正在尝试向 Stomp 端点发送消息,但我没有收到 any.I 我正在使用 spring 启动,下面是我的 类

@Controller
public class GreetingController {

  @MessageMapping("/hello")
  @SendTo("/topic/greetings")
  public Greeting greeting(HelloMessage message) throws Exception {
    System.out.println(message.getName());
    Thread.sleep(13000); // simulated delay
    return new Greeting("Hello, " + message.getName() + "!");
  }

}

@Controller                                                
public class Testcont {

  @Autowired
  private SimpMessagingTemplate messageSender;

  @RequestMapping(value="/Users/get",method=RequestMethod.POST)
  @ResponseBody
  public String getUser(@RequestParam(value = "userId") String userId, @RequestParam(value = "password") String password, @RequestParam(value="port") String port, HttpServletRequest request) {
    HelloMessage mess=new HelloMessage();
    mess.setName(userId);
    messageSender.convertAndSend("/app/hello",mess);
    return "Success";

}

和我的 websocket 配置

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/hello").withSockJS();
    }

}

我在控制台中没有收到任何错误。上面的代码在网络浏览器上运行良好。

SimpMessagingTemplate bean 正是用于 Broker 部分 (AbstractMessageBrokerConfiguration):

@Bean
public SimpMessagingTemplate brokerMessagingTemplate() {
    SimpMessagingTemplate template = new SimpMessagingTemplate(brokerChannel());
    String prefix = getBrokerRegistry().getUserDestinationPrefix();
    if (prefix != null) {
        template.setUserDestinationPrefix(prefix);
    }

由于您没有将消息发送到代理目的地(在您的情况下为 /app/),因此 AbstractBrokerMessageHandler.checkDestinationPrefix(destination) 会忽略此类消息。

如果您想通过相同的 @MessageMapping 处理该内部消息,您应该直接使用 clientInboundChannel,它由 SimpAnnotationMethodMessageHandler 提供:

@Bean
public SimpAnnotationMethodMessageHandler simpAnnotationMethodMessageHandler() {
    SimpAnnotationMethodMessageHandler handler = createAnnotationMethodMessageHandler();
    handler.setDestinationPrefixes(getBrokerRegistry().getApplicationDestinationPrefixes());

我想您可以为 clientInboundChannel 创建自己的 SimpMessagingTemplate 实例,类似于那个 brokerMessagingTemplate bean。你会没事的。

我在使用 WebSocket 时遇到了同样的问题。这个 post 为时已晚,但可能对正在寻找答案的人有用。

SimpMessagingTemplate -> 使用 "topic" 而不是 "app" 所以 messageSender.convertAndSend("/topic/hello",混乱);将是一个解决方案。

来自上面提到的 WebSocket 文档:

"clientInboundChannel"⟩—⟩用于传递从 WebSocket 客户端接收的消息。

"clientOutboundChannel"⟩—⟩用于向 WebSocket 客户端发送服务器消息。

"brokerChannel"⟩—⟩用于从应用程序代码 server-side 中向消息代理发送消息。

  1. 客户端连接到“http://localhost:8080/portfolio”,一旦建立了 WebSocket 连接,STOMP 帧就开始在其上流动。 (在你的情况下: registry.addEndpoint("/hello").withSockJS(),你用的是"hello",文档里用的是"portfolio"。)

  2. 客户端发送目标为 header“/topic/hello”的 SUBSCRIBE 帧。收到并解码后,消息将发送到 "clientInboundChannel",然后路由到存储客户端订阅的消息代理。 (这是UI订阅了WebSocket,你这里没有代码。没关系。)

  3. 客户端将 SEND 帧发送到“/app/hello”。 “/app”前缀有助于将其路由到带注释的控制器。去掉“/app”前缀后,destination 剩余的“/hello”部分映射到GreetingController 中的@MessageMapping 方法。 (在您的代码中:@MessageMapping("/hello") 将接收框架。)

  4. 来自 GreetingController 的 return 值被转换为 Spring 消息,其有效负载基于 return 值和默认目标 header 的“/topic/hello”(源自输入目的地,“/app”替换为“/topic”)。生成的消息被发送到 "brokerChannel" 并由消息代理处理。 ( 所以当你试图把数据放在服务器的 WebSocket 中时: messageSender.convertAndSend("/app/hello",mess); 应该改为 messageSender.convertAndSend("/topic/hello",mess), 因为它已经在服务器中了,所以我们不需要目标前缀,但是我们需要代理前缀。)

  5. 消息代理找到所有匹配的订阅者,并通过 "clientOutboundChannel" 向每个订阅者发送一个 MESSAGE 帧,消息从那里被编码为 STOMP 帧并在 WebSocket 连接上发送。