前言
紧接着上文《SpringBoot+WebSocket实现即时通讯(一)》
本博客姊妹篇
- SpringBoot+WebSocket实现即时通讯(一)
- SpringBoot+WebSocket实现即时通讯(二)
- SpringBoot+WebSocket实现即时通讯(三)
- SpringBoot+WebSocket实现即时通讯(四)
一、功能描述
- 用户管理:业务自己实现,暂从数据库添加
- 好友管理:添加好友、删除好友、修改备注、好友列表等
- 群组管理:新建群、解散群、编辑群、变更群主、拉人进群、踢出群等
- 聊天模式:私聊、群聊
- 消息类型:系统、文本、语音、图片、视频
- 聊天管理:删除聊天、置顶聊天、查看聊天记录等
二、沟通功能设计
2.1 数据库设计
sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for im_chat
-- ----------------------------
DROP TABLE IF EXISTS `im_chat`;
CREATE TABLE `im_chat` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_id` bigint NOT NULL COMMENT '用户id',
`chat_type` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '聊天类型:01-私聊 02-群聊',
`target_id` bigint NOT NULL COMMENT '聊天对象id',
`top_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '置顶标志',
`del_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '更新人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天会话' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for im_friend
-- ----------------------------
DROP TABLE IF EXISTS `im_friend`;
CREATE TABLE `im_friend` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_id` bigint NOT NULL COMMENT '用户id',
`friend_user_id` bigint NOT NULL COMMENT '好友用户id',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '好友备注',
`del_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '更新人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for im_group
-- ----------------------------
DROP TABLE IF EXISTS `im_group`;
CREATE TABLE `im_group` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '群名称',
`avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群头像',
`master` bigint NULL DEFAULT NULL COMMENT '群主',
`manager` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群管理',
`notice` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '公告',
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
`del_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '更新人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群组' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for im_group_user
-- ----------------------------
DROP TABLE IF EXISTS `im_group_user`;
CREATE TABLE `im_group_user` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`group_id` bigint NOT NULL COMMENT '群id ',
`user_id` bigint NOT NULL COMMENT '用户id',
`nick_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '群昵称',
`del_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '更新人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群成员' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for im_message
-- ----------------------------
DROP TABLE IF EXISTS `im_message`;
CREATE TABLE `im_message` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`chat_id` bigint NULL DEFAULT NULL COMMENT '聊天会话id',
`sender_id` bigint NULL DEFAULT NULL COMMENT '发送者id',
`message_type` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '消息类型:00-系统、02-文本、03-图片、04-音频、05-视频',
`message` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '消息',
`del_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '更新人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '消息' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for im_message_receiver
-- ----------------------------
DROP TABLE IF EXISTS `im_message_receiver`;
CREATE TABLE `im_message_receiver` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`message_id` bigint NOT NULL COMMENT '消息id',
`receiver_id` bigint NOT NULL COMMENT '接收者id',
`read_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '已读标志',
`del_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '更新人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '接收者消息' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`dept_id` bigint NULL DEFAULT NULL COMMENT '部门id',
`user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账号',
`password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密码',
`nick_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '昵称',
`email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户邮箱',
`phone_number` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '手机号码',
`sex` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '用户性别(0男 1女)',
`avatar` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '头像地址',
`status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '帐号状态(0正常 1停用)',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
`del_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '删除标志',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '更新人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户信息' ROW_FORMAT = DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;
2.2 引入依赖
xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
2.3 配置
yaml
# 服务配置
server:
port: 8007
# springboot配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/boot_business?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# mybatis-plus配置
mybatis-plus:
type-aliases-package: com.qiangesoft.im.entity
mapper-locations: classpath*:mapper/*Mapper.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2.4 实体类
java
package com.qiangesoft.im.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 聊天会话
* </p>
*
* @author qiangesoft
* @date 2024-02-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ImChat implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 聊天类型:01-私聊 02-群聊
*/
private String chatType;
/**
* 聊天对象id
*/
private Long targetId;
/**
* 置顶标志
*/
private Boolean topFlag;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 最后更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
java
package com.qiangesoft.im.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 好友
* </p>
*
* @author qiangesoft
* @date 2024-02-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ImFriend implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 好友用户id
*/
private Long friendUserId;
/**
* 好友备注
*/
private String remark;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 最后更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
java
package com.qiangesoft.im.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 群组
* </p>
*
* @author qiangesoft
* @date 2024-02-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ImGroup implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 群名称
*/
private String name;
/**
* 群头像
*/
private String avatar;
/**
* 群主
*/
private Long master;
/**
* 群主
*/
private String manager;
/**
* 公告
*/
private String notice;
/**
* 备注
*/
private String remark;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
java
package com.qiangesoft.im.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 群成员
* </p>
*
* @author qiangesoft
* @date 2024-02-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ImGroupUser implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 群id
*/
private Long groupId;
/**
* 用户id
*/
private Long userId;
/**
* 昵称
*/
private String nickName;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 最后更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
java
package com.qiangesoft.im.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 消息
* </p>
*
* @author qiangesoft
* @date 2024-02-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ImMessage implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 聊天会话id
*/
private Long chatId;
/**
* 发送者id
*/
private Long senderId;
/**
* 消息类型:01-系统、02-文本、03-图片、04-音频、05-视频
*/
private String messageType;
/**
* 消息
*/
private String message;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 最后更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
java
package com.qiangesoft.im.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 接收者消息
* </p>
*
* @author qiangesoft
* @since 2023-08-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class ImMessageReceiver implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 消息id
*/
private Long messageId;
/**
* 接收者id
*/
private Long receiverId;
/**
* 已读标志
*/
private Boolean readFlag;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 最后更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
java
package com.qiangesoft.im.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 用户
* </p>
*
* @author qiangesoft
* @date 2024-02-07
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysUser implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 部门id
*/
private Long deptId;
/**
* 账号
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 昵称
*/
private String nickName;
/**
* 用户邮箱
*/
private String email;
/**
* 手机号码
*/
private String phoneNumber;
/**
* 用户性别
*/
private String sex;
/**
* 用户头像
*/
private String avatar;
/**
* 帐号状态(0正常 1停用)
*/
private String status;
/**
* 备注
*/
private String remark;
/**
* 删除标志
*/
private Boolean delFlag;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 最后更新人
*/
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
/**
* 最后更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}
2.5 接口文档
xml
<!-- knife4j依赖 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
java
package com.qiangesoft.im.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* Knife4j的接口配置
*
* @author qiangesoft
*/
@Configuration
@EnableKnife4j
public class Knife4jConfig {
@Bean
public Docket docket() {
return new Docket(DocumentationType.SWAGGER_2)
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(this.apiInfo())
// 设置哪些接口展示
.select()
// 扫描指定包
.apis(RequestHandlerSelectors.basePackage("com.qiangesoft.im.controller"))
.build();
}
/**
* 添加摘要信息
*/
private ApiInfo apiInfo() {
// 用ApiInfoBuilder进行定制
return new ApiInfoBuilder()
// 设置标题
.title("标题:即时通讯_接口文档")
// 描述
.description("描述:用于管理即时通讯的接口")
// 作者信息
.contact(new Contact("qiangesoft", null, null))
// 版本
.version("v1.0.0")
.build();
}
}
查看接口文档
三、源码地址
源码地址:https://gitee.com/qiangesoft/boot-business/tree/master/boot-business-im
后续内容见下章