WebSocket 实时聊天
源码
源码包括:
- 源码地址 : websocket-gitee仓库
- websocket 聊天室,前后端代码
- websocket 查看历史消息
- 采用springsecurity作为鉴权
- 前端代码在 resources static 下,好处:打开springboot端口就是改页面:
– 例如:localhost:8080- 项目采用渐进式,共有四个项目
坐标导入
由于SpringBoot集成WebSocket,因此版本号即为springboot版本号,一般情况无需配置版本号
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
配置文件
在springboot集成的websocket中,主要操作的是Session
Session配置
public class SessionConfig extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
if (httpSession != null) {
sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
System.out.println("[websocket] 获取HttpSession成功");
} else {
System.err.println("在WebSocket握手期间HttpSession为空");
}
}
}
服务类
配置请求 ws:// 地址,使用配置类
处理连接中常用的四种状态 :
- 连接打开
- 消息处理
- 连接异常
- 连接关闭
@Slf4j
@ServerEndpoint(value = "/ws", configurator = SessionConfig.class)
public class ChatChannel{
private Session session;
// 连接打开
@OnOpen
public void onOpen(Session session, EndpointConfig endpointConfig){
// 保存 session 到对象
this.session = session;
//获取存储的用户信息
Object o = endpointConfig.getUserProperties().get(HttpSession.class.getName());
log.info("[websocket] 新的连接:用户id{} id={}", o, this.session.getId());
}
// 收到消息
@OnMessage
public void onMessage(String message) throws IOException{
log.info("[websocket] 收到消息:id={},message={}", this.session.getId(), message);
this.session.getAsyncRemote().sendText("[" + Instant.now().toEpochMilli() + "] Hello " + message);
}
// 连接关闭
@OnClose
public void onClose(CloseReason closeReason){
log.info("[websocket] 连接断开:id={},reason={}", this.session.getId(), closeReason);
}
// 连接异常
@OnError
public void onError(Throwable throwable) throws IOException{
log.info("[websocket] 连接异常:id={},throwable={}", this.session.getId(), throwable.getMessage());
// 关闭连接。状态码为 UNEXPECTED_CONDITION(意料之外的异常)
this.session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, throwable.getMessage()));
}
}
配置websocket服务
主要目的 : 告诉spring将服务自动装配到bean容器中
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
ServerEndpointExporter exporter = new ServerEndpointExporter();
exporter.setAnnotatedEndpointClasses(ChatChannel.class);
return exporter;
}
}
连接测试
为了简化,这里采用连接工具 : ApiPost
关于连接异常
关于连接异常的文章查看我的内外一篇文章:
websocket 连接异常