我首先的问题是,当你成功地将websockets与踩踏集成时,为什么你试图向休息控制器发送http请求?如果我正确理解了您的用例,那么我可以想到atm应该有三种解决方案。
解决方案 1(套接字会话↔产品 ID)
您可以通过打开的 websocket 连接将请求直接从客户端发送到服务器。然后,Spring 可以确定哪个 Websocket 会话进行了调用,并且您可以实现业务逻辑。您需要激活另一个名为“/queue”的代理,并为订阅不用于广播时所需的用户目标指定前缀。在客户端,还必须更改订阅路径。最后,必须创建一个使用@Controller注释的类,该类包含消息映射,以便从连接的客户端接收消息。
服务器配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/queue", "/product"); // <- added "/queue"
registry.setApplicationDestinationPrefixes("/app");
registry.setUserDestinationPrefix("/user");
}
}
服务器控制器
@Controller
public class WebSocketContoller{
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/product/register")
public void register(@Payload Long productId, @Header("simpSessionId") String sessionId) {
// register current websocket session with product id and
// then with convertAndSendToUser send changes to current user.
// Example of how to send a message to the user using the sessionId
String response = "This could also be one of your product objects of type Product";
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
headerAccessor.setSessionId(sessionId);
headerAccessor.setLeaveMutable(true);
messagingTemplate.convertAndSendToUser(sessionId,"/queue/product/changes", response, headerAccessor.getMessageHeaders());
}
}
客户端订阅更改
stompClient.subscribe('/user/queue/product/changes', function (scoredata) {
// We received product changes
});
有关详细信息,您还可以查看此答案:https://stackoverflow.com/a/26288475/11133168
解决方案 2(主↔产品 ID)
但是,如果您真的想考虑使用 rest 控制器开始注册您的进程,或者如果它只是不符合您的要求,则应查看下面的链接。Spring还能够通过公开的SimpUserRegistry bean跟踪活动的websocket会话及其用户。但是,您需要为客户端输入通道配置自定义通道接收器适配器,具体取决于应用程序的安全性,以确定用户。有关详细信息和代码示例,请查看此答案:https://stackoverflow.com/a/45359294/11133168
解决方案 3(产品 ID 主题)
您还可以订阅特定的产品 ID 主题,这样您甚至不需要知道哪个用户希望收到有关特定产品更改的通知。
客户端订阅更改
//e.g if you want to be notified about changes for products with id 5
stompClient.subscribe('/product/changes/5', function (scoredata) {
// We received product changes
});
服务器服务示例
@Service
public class WebSocketProductService{
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
// This would be the method which should inform your clients about specific product
// changes, instead of the String parameters a Product object should be used instead,
// you have to call this method yourself on product changes or schedule it or sth.
public void sendProductChange(String product, String productId) {
this.simpMessagingTemplate.convertAndSend("/product/changes/"+productId, product);
}
}
服务器控制器
如果要管理产品 ID 订阅的列表,则需要此项。如解决方案 1 中所述,您需要一个用 @Controller 注释的类,其中包含一个用 @SubscribeMapping 注释的方法。如果客户端尝试订阅指定的路径,则调用此方法。
@Controller
public class WebSocketContoller{
@SubscribeMapping("/product/changes/{productId}")
public void productIdSubscription(@DestinationVariable Long productId) {
//Manage your product id subscription list e.g.
}
}