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 中向消息代理发送消息。
客户端连接到“http://localhost:8080/portfolio”,一旦建立了 WebSocket 连接,STOMP 帧就开始在其上流动。 (在你的情况下:
registry.addEndpoint("/hello").withSockJS(),你用的是"hello",文档里用的是"portfolio"。)
客户端发送目标为 header“/topic/hello”的 SUBSCRIBE 帧。收到并解码后,消息将发送到 "clientInboundChannel",然后路由到存储客户端订阅的消息代理。 (这是UI订阅了WebSocket,你这里没有代码。没关系。)
客户端将 SEND 帧发送到“/app/hello”。 “/app”前缀有助于将其路由到带注释的控制器。去掉“/app”前缀后,destination 剩余的“/hello”部分映射到GreetingController 中的@MessageMapping 方法。 (在您的代码中:@MessageMapping("/hello") 将接收框架。)
来自 GreetingController 的 return 值被转换为 Spring 消息,其有效负载基于 return 值和默认目标 header 的“/topic/hello”(源自输入目的地,“/app”替换为“/topic”)。生成的消息被发送到 "brokerChannel" 并由消息代理处理。 ( 所以当你试图把数据放在服务器的 WebSocket 中时: messageSender.convertAndSend("/app/hello",mess); 应该改为 messageSender.convertAndSend("/topic/hello",mess), 因为它已经在服务器中了,所以我们不需要目标前缀,但是我们需要代理前缀。)
消息代理找到所有匹配的订阅者,并通过 "clientOutboundChannel" 向每个订阅者发送一个 MESSAGE 帧,消息从那里被编码为 STOMP 帧并在 WebSocket 连接上发送。
大家好,我正在尝试向 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 中向消息代理发送消息。
客户端连接到“http://localhost:8080/portfolio”,一旦建立了 WebSocket 连接,STOMP 帧就开始在其上流动。 (在你的情况下: registry.addEndpoint("/hello").withSockJS(),你用的是"hello",文档里用的是"portfolio"。)
客户端发送目标为 header“/topic/hello”的 SUBSCRIBE 帧。收到并解码后,消息将发送到 "clientInboundChannel",然后路由到存储客户端订阅的消息代理。 (这是UI订阅了WebSocket,你这里没有代码。没关系。)
客户端将 SEND 帧发送到“/app/hello”。 “/app”前缀有助于将其路由到带注释的控制器。去掉“/app”前缀后,destination 剩余的“/hello”部分映射到GreetingController 中的@MessageMapping 方法。 (在您的代码中:@MessageMapping("/hello") 将接收框架。)
来自 GreetingController 的 return 值被转换为 Spring 消息,其有效负载基于 return 值和默认目标 header 的“/topic/hello”(源自输入目的地,“/app”替换为“/topic”)。生成的消息被发送到 "brokerChannel" 并由消息代理处理。 ( 所以当你试图把数据放在服务器的 WebSocket 中时: messageSender.convertAndSend("/app/hello",mess); 应该改为 messageSender.convertAndSend("/topic/hello",mess), 因为它已经在服务器中了,所以我们不需要目标前缀,但是我们需要代理前缀。)
消息代理找到所有匹配的订阅者,并通过 "clientOutboundChannel" 向每个订阅者发送一个 MESSAGE 帧,消息从那里被编码为 STOMP 帧并在 WebSocket 连接上发送。