一、为什么有websocket
主流web应用使用的http协议只能进行单向访问,要想实时通信只能通过轮询的方式实现,而高频度的轮询十分消耗性能,此时就体现了websocket的优点
1.支持双向通信,可以实现服务端与客户端的主动收发消息
2.较少的控制开销:在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小
二、Websocket简介
WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层
websocket应用场景:
1.聊天室
2.实时告警
三、Websocket应用(Java springboot)
1.引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.创建配置类
@Configuration
//@EnableWebSocketMessageBroker
@EnableWebSocket
public class WSConfig implements WebSocketConfigurer {
@Autowired
private MyWebSocketHandler webSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(webSocketHandler, "/my-websocket").setAllowedOrigins("*");
}
}
这里可以使用@EnableWebSocket(简单应用) 或者 @EnableWebSocketMessageBroker(消息代理功能 通俗的讲就是复杂封装了)
@EnableWebSocketMessageBroker:该配置类中使用@EnableWebSocketMessageBroker注解来启用WebSocket消息代理功能,使用configureMessageBroker方法来配置消息代理的相关参数,使用registerStompEndpoints方法来注册Stomp协议的WebSocket端点
3.创建处理类
这里需要使用webSocketSession 进行收发消息,而正常在业务类中获取webSocketSession 较为复杂,这里使用封装好的方法里获取,即建立连接时执行afterConnectionEstablished方法,在这里保存session,断开连接执行afterConnectionClosed,删除session
@Component
@Slf4j
public class MyWebSocketHandler extends TextWebSocketHandler{
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessions.add(session);
log.info("WebSocket connection established");
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String payload = message.getPayload();
log.info("Received message: " + payload);
// 回复消息给客户端
try {
session.sendMessage(new TextMessage("Hello, client! You said: " + payload));
} catch (IOException e) {
log.error("Error sending message to session: " + session.getId(), e);
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
sessions.remove(session);
log.info("WebSocket connection closed");
}
private static final CopyOnWriteArrayList<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
public void sendMessageToAll(String message) {
// log.info("Sending message to all sessions: {}", message);
for (WebSocketSession session : sessions) {
try {
session.sendMessage(new TextMessage(message));
log.info("Sending message to all sessions: successful");
} catch (IOException e) {
log.error("Error sending message to session {}: {}", session.getId(), e.getMessage());
}
}
}
}
4.实际业务类中使用
通过控制台日志可以查看收发消息是否成功
@Override
public void run(ApplicationArguments args) throws Exception{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
while (true){
Thread.sleep(3000);
String time = simpleDateFormat.format(new Date());
webSocketHandler.sendMessageToAll("发送消息咯 --- " + time);
}
}