记一次WebSocket代码调试
由于项目需要,需要通过WebSocket以及MQTT实现设备之间的通信及数据传输,为此特意搭建了一下WebSocket相关内容,做个记录。
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.4.3</version>
</dependency>
创建配置类
@Configuration
@EnableWebSocketMessageBroker
@Slf4j
public class WsConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket/**")
.setAllowedOriginPatterns("*")
.setHandshakeHandler(new PrincipalHandshakeHandler())
// .withSockJS() 此处为websocket连接是否浏览器访问,不开启则为 ws:// wss://,开启为 http:// https://
;
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 订阅Broker名称 user点对点 topic广播即群发
registry.enableSimpleBroker("/topic", "/user");
registry.setUserDestinationPrefix("/user");
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
registry.addDecoratorFactory(new DeWsHandlerFactory());
registry.setMessageSizeLimit(8192) //设置消息字节数大小
.setSendBufferSizeLimit(8192)//设置消息缓存大小
.setSendTimeLimit(10000); //设置消息发送时间限制毫秒
}
@EventListener
public void onDisconnectEvent(SessionDisconnectEvent event) {
String sessionId=event.getSessionId();
log.info("监听到websocket连接断开,id为[{}]",sessionId);
}
//断开事件监听
@EventListener
public void handleWebSocketConnectListener(SessionConnectedEvent event) {
StompPrincipal principal = toBean(toJsonStr(event.getUser()), StompPrincipal.class);
log.info("WebSocket 客户端已连接: {}",
"{ 客户端主机名: " + principal.getName() +
", 客户端主机IP地址: " + principal.getPublicName() +
", 会话ID: " + requireNonNull(event.getMessage().getHeaders().get("simpSessionId")) + " }");
}
}
消息发送
public interface WsDeviceService {
void sendMessage(WsMessage wsMessage, String username);
}
@Service
@Slf4j
public class WsDeviceServiceImpl implements WsDeviceService {
@Resource
private SimpMessagingTemplate messagingTemplate;
@Override
public void sendMessage(WsMessage wsMessage, String username) {
if(ObjectUtils.isEmpty(wsMessage) || ObjectUtils.isEmpty(wsMessage.getTopic())) return;
log.info("发送数据消息,数据内容为-->[{}]",wsMessage.getData());
messagingTemplate.convertAndSend("/topic/device/"+username,wsMessage.getData());
log.info("完成数据发送。");
}
}
controller代码不做赘述,太简单
调试阶段出现的问题
websocket连接不上
Invalid SockJS path ‘/xxxx/Xxxx’ - required to have 3 path segments
配置类修改,注释掉withSockJS(),不开启sockjs
registry.addEndpoint("/websocket/**")
.setAllowedOriginPatterns("*")
.setHandshakeHandler(new PrincipalHandshakeHandler())
// .withSockJS()