使用SpringBoot + WebSocket 实现模拟QQ聊天功能
登录界面展示
登录界面模仿QQ登录操作,支持拖动、最小化和关闭
聊天界面展示
登录后的右侧显示在线用户,右下方显示在线用户的登录日志
窗口支持拖动、关闭操作
发送消息界面展示
在线用户实现及时聊天功能,可以对指定用户发起聊天(实现点对点的消息推送功能)
支持消息的本地缓存,聊天内容不会因为页面的刷新、关闭、退出登录等操作而丢失(消息只是做了简单缓存),清理浏览器缓存数据时消息数据便会丢失。
点对点消息推送,实现一对一的即时通信功能
Demo的目录代码
该Demo主要使用的是
SpringBoot + WebSocket
技术实现
下面是Demo的后端代码实现及说明
创建SpringBoot项目,导入依赖
项目pom依赖配置
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<!-- springboot-Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- WebSocket组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 热部署依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
<!-- ****************************以下工具为非必须**************************** -->
<!-- lang3工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.16</version>
</dependency>
<!-- slf4j日志处理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- fastjson,对象和JSON数据转换工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.55</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打jar包时 如果 不配置该插件,打出来的jar包没有清单文件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
项目配置文件说明
application.properties
# 项目名称
spring.application.name=websocket-chatroom
# 配置资源路径
spring.resource.static-locations=classpath:/static/
# 视图前缀配置
spring.mvc.view.prefix=/chat/
# 视图后缀配置
spring.mvc.view.suffix=.html
###########################【热部署】#########################
# 重启目录
spring.devtools.restart.additional-paths=src/main/java
# 设置开启热部署
spring.devtools.restart.enabled=true
# 设置字符集
spring.freemarker.charset=utf-8
# 页面不加载缓存,修改后立即生效
spring.freemarker.cache=false
# 服务端口配置
server.port=80
application.yml
spring:
resource:
static-locations: classpath:/static/
application:
name: websocket-chatroom
mvc:
view:
suffix: .html
prefix: /chat/
devtools:
restart:
additional-paths: src/main/java
enabled: true
freemarker:
charset: utf-8
cache: false
server:
port: 80
项目的配置类说明
WebConfig.java
WebConfig 配置类
配置后项目启动时,访问默认项目路径时,会跳转到该类指定的页面中
/**
* @title web配置类 设置默认访问页面
* @author 陌路
* @date 2022-04-16
* @apiNote 配置默认页面
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 自定义静态路径,spring.resource.static-locations=classpath:/static/
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("/chat/login");
}
}
WebSocketConfig.java
使用WebSocket前首先配置 @ServerEndpoint
首先需要注入 ServerEndpointExporter ,
这个bean会自动注册使用 @ServerEndpoint 注解来声明WebSocket endpoint。
注意:如果使用独立的Servlet容器,而不是直接使用SpringBoot内置容器,就不需要注入 ServerEndpointExporter,因为他将由容器自己提供和管理。
/**
* @Desc 首先需要注入 ServerEndpointExporter ,
* 这个bean会自动注册使用 @ServerEndpoint 的注解来声明WebSocket endpoint。
* 注意:如果使用独立的Servlet容器,而不是直接使用SpringBoot内置容器,就不需要注入
* ServerEndpointExporter,因为他将有容器自己提供和管理。
* @author 陌路
* @date 2022-04-16
*/
@Configuration
public class WebSocketConfig {
/**
* @title 扫描注册使用 @ServerEndpoint 注解的类
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
GetHttpSessionConfigurator.java
该类可以在建立连接后存放HttpSession,方便后续的使用
用户建立连接时,通过
EndpointConfig
获取存在session
中的用户数据
/**
* @tite 用来获取HttpSession对象.
* @author 陌路
* @date 2022-04-16
*/
public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
/**
* @title 该配置可以在不手动传入HttpSession的情况下在websocket服务类中使用
*/
@Override
public void modifyHandshake(ServerEndpointConfig sec,
HandshakeRequest request,
HandshakeResponse response) {
// 获取httpsession对象
HttpSession httpSession = (HttpSession) request.getHttpSession();
// 存放httpsession对象
Map<String, Object> userProperties = sec.getUserProperties();
userProperties.put(HttpSession.class.getName(), httpSession);
}
}
创建用户对象实体
/**
* (User)实体类
* @author 陌路
* @since 2022-04-16
*/
@Data
public class User implements Serializable {
private static final long serialVersionUID = -31513108721728277L;
/** 用户id */
private String userId;
/** 用户名 */
private String username;
/** 用户手机号 */
private String phone;
/** 用户密码 */
private S