我有一个带有WebSockets的应用程序,该应用程序使用spring-boot应用程序作为后端,并在客户端使用Stomp / SockJS,spring-boot应用程序使用JMS队列消息并将更改通知给正确的用户。问题是什么?有时可行,有时不可行,相同的代码和用户可以正常工作。
在这里,客户端代码很难复制,因为它是通过react / redux应用程序集成的,但是基本上是对两个不同通道的订阅,这两个通道都在Spring的配置中定义。会话是根据调试信息正确创建的,但有时会处理该消息以将其发送到连接的会话。
这是Spring的配置类。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/stomp")
.setAllowedOrigins("*")
.withSockJS();
}
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry
.setApplicationDestinationPrefixes("/app")
.enableSimpleBroker("/xxxx/yyyy", "/ccccc");
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor =
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
Object raw = message
.getHeaders()
.get(SimpMessageHeaderAccessor.NATIVE_HEADERS);
if (raw instanceof Map) {
Object name = ((Map<?,?>) raw).get("email");
if (name instanceof LinkedList) {
String user = ((LinkedList<?>) name).get(0).toString();
accessor.setUser(new User(user));
}
}
}
return message;
}
});
}
}
这是JMS侦听器,用于处理队列消息并将其发送给特定用户。
@Component
public class UserEventListener {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final SimpMessagingTemplate template;
@Autowired
public UserEventListener(SimpMessagingTemplate pTemplate) {
this.template = pTemplate;
}
@JmsListener(destination="user/events")
public void onStatusChange(Map<String, Object> props) {
if (props.containsKey("userEmail")) {
logger.debug("Event for user received: {}", props.get("userEmail"));
template.convertAndSendToUser((String)props.get("userEmail"), "/ccccc", props);
}
}
}
编辑1:
经过更多的调试之后,WebSocket的“会话”似乎因Spring配置而丢失了。我没有看到有关“断开连接”消息或类似内容的任何日志信息,此外,如果在发生这种情况时远程调试服务器,则在调试会话期间不会出现问题。有想法吗来自Spring的会话消失的班级是DefaultSimpUserRegistry
。
答案 0 :(得分:0)
经过更多研究,我发现了一个具有相同问题的问题和解决方案here。基本上结论是这样的:
通道拦截器不是验证用户身份的正确位置,我们需要使用自定义的握手处理程序对其进行更改。