Я использую spring-boot-websocket
(spring-boot
версия 1.5.10
) в моем проекте. Я настроил его следующим образом:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends WebSocketMessageBrokerConfigurationSupport
implements WebSocketMessageBrokerConfigurer {
@Value( "${rabbitmq.host}" )
private String rabbitmqHost;
@Value( "${rabbitmq.stomp.port}" )
private int rabbitmqStompPort;
@Value( "${rabbitmq.username}" )
private String rabbitmqUserName;
@Value( "${rabbitmq.password}" )
private String rabbitmqPassword;
@Override
public void configureMessageBroker( MessageBrokerRegistry registry )
{
registry.enableStompBrokerRelay("/topic", "/queue").setRelayHost(rabbitmqHost).setRelayPort(rabbitmqStompPort)
.setSystemLogin(rabbitmqUserName).setSystemPasscode(rabbitmqPassword);
registry.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints( StompEndpointRegistry stompEndpointRegistry )
{
stompEndpointRegistry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
}
@Bean
@Override
public WebSocketHandler subProtocolWebSocketHandler()
{
return new CustomSubProtocolWebSocketHandler(clientInboundChannel(), clientOutboundChannel());
}
@Override
public void configureWebSocketTransport( WebSocketTransportRegistration registry )
{
super.configureWebSocketTransport(registry);
}
@Override
public boolean configureMessageConverters( List<MessageConverter> messageConverters )
{
return super.configureMessageConverters(messageConverters);
}
@Override
public void configureClientInboundChannel( ChannelRegistration registration )
{
super.configureClientInboundChannel(registration);
}
@Override
public void configureClientOutboundChannel( ChannelRegistration registration )
{
super.configureClientOutboundChannel(registration);
}
@Override
public void addArgumentResolvers( List<HandlerMethodArgumentResolver> argumentResolvers )
{
super.addArgumentResolvers(argumentResolvers);
}
@Override
public void addReturnValueHandlers( List<HandlerMethodReturnValueHandler> returnValueHandlers )
{
super.addReturnValueHandlers(returnValueHandlers);
}
}
public class CustomSubProtocolWebSocketHandler extends SubProtocolWebSocketHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomSubProtocolWebSocketHandler.class);
@Autowired
private UserCommons userCommons;
CustomSubProtocolWebSocketHandler(MessageChannel clientInboundChannel,
SubscribableChannel clientOutboundChannel) {
super(clientInboundChannel, clientOutboundChannel);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
LOGGER.info("************************************************************************************************************************New webSocket connection was established: {}", session);
String token = session.getUri().getQuery().replace("token=", "");
try
{
String user = Jwts.parser().setSigningKey(TokenConstant.SECRET)
.parseClaimsJws(token.replace(TokenConstant.TOKEN_PREFIX, "")).getBody().getSubject();
Optional<UserModel> userModelOptional = userCommons.getUserByEmail(user);
if( !userModelOptional.isPresent() )
{
LOGGER.error(
"************************************************************************************************************************Invalid token is passed with web socket request");
throw new DataException(GeneralConstants.EXCEPTION, "Invalid user", HttpStatus.BAD_REQUEST);
}
}
catch( Exception e )
{
LOGGER.error(GeneralConstants.ERROR, e);
}
super.afterConnectionEstablished(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
LOGGER.error("************************************************************************************************************************webSocket connection was closed");
LOGGER.error("Reason for closure {} Session: {} ", closeStatus.getReason(),session.getId() );
super.afterConnectionClosed(session, closeStatus);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
LOGGER.error("************************************************************************************************************************Connection closed unexpectedly");
LOGGER.error(GeneralConstants.ERROR, exception);
super.handleTransportError(session, exception);
}
}
На стороне клиента я создаю объект SockJS
для установления sh соединения,
let url = `/ws?token=${localStorage.getItem("access_token")}`;
// Web Socket connection
/* eslint-disable */
let sockJS = new SockJS(url);
let stompClient = Stomp.over(sockJS);
debugger
this.setState({
stompObject : stompClient,
});
Но соединение не устанавливается постоянно, в большинстве случаев он застревает на Opening the connection
, в журнале бэкэнда я вижу, как устанавливается соединение и создается сеанс. Но в консоли браузера я вижу отправку сообщения на сервер на стороне клиента, но сервер не подтверждает сообщение.
![enter image description here](https://i.stack.imgur.com/ACCF5.png)
![enter image description here](https://i.stack.imgur.com/gyfUz.png)
Иногда, когда я обновляю sh браузер 10-15 раз, соединение устанавливается успешно. Есть ли ошибка в моей конфигурации?
Спасибо.