SpringBoot与webSocket实现在线聊天室——实现私聊+群聊+聊天记录保存

本文介绍了如何使用SpringBoot和WebSocket实现一个包含私聊和群聊功能的在线聊天室,并详细阐述了聊天记录的存储策略。通过创建UserMessage实体类保存聊天记录,利用静态集合MessageList暂存聊天记录,达到批量保存至数据库以降低数据库操作频率的效果。此外,还讨论了在实现过程中遇到的问题和解决方案。
摘要由CSDN通过智能技术生成

SpringBoot与webSocket实现在线聊天室——实现私聊+群聊+聊天记录保存

引用参考:原文章地址:https://blog.csdn.net/qq_41463655/article/details/92410518

在此基础上实现对聊天记录的保存。

代码地址:链接:https://pan.baidu.com/s/1IJFZDa4S_DF08773sKJWeA 提取码:jkui
思路:新建一个实体类用于保存聊天记录,在消息发送时,设置对象的各个值然后保存到数据库中。
实现步骤:
  1. 实体类: 新建实体类UserMessage,根据需要设置对象的字段,如:发送者、接收者、信息内容、发送时间等。
  2. mapper层:写UserMessageMapper接口,继承BaseMapper(我使用的是mybatis-plus,也可以使用其他方法)。
  3. service层:UserMessageService继承IService,service实现类UserMessageServiceImpl继承ServiceImpl<UserMessageMapper, UserMessage> 实现UserMessageService。
  4. controller层:在UserMessageController中的onMessage方法中,将前端传过来的json解析为字段,新建UserMessage对象message1,设置message1对象的各个值,通过消息接收者类型的判断,确实数据库中接收者的值如何设置,然后将UserMessage对象保存到数据库中。
此时,聊天记录保存到数据库时,是一条一条进行保存,为了减少对数据库频繁的操作,在UserMessageController类中定义一个静态的集合MessageList用来暂时保存聊天记录,并且设置MessageList集合的长度为一个固定值不可变,目的是为了实现将聊天记录保存到集合中,当集合的长度等于设定的值时,批量将聊天记录保存到数据库中。
  1. 所以将聊天记录保存到数据库前,先将聊天记录保存到集合MessageList中,判断集合的长度,如果集合的长度等于设定的值,将集合中的数据批量保存到数据库中,然后清空集合,为下一次保存聊天记录做准备。
我在实现保存聊天记录功能时遇到的问题:
  1. 代码没有错,群聊、私聊都可以实现,但是无法保存聊天记录,错:设置的表名与数据库没有对应好。
  2. 保存聊天记录的集合一定要设置为全局,如果是在方法中新建集合,那么聊天记录保存的并不是同一个集合,导致集合的长度永远无法达到设定的值,无法批量保存,导致数据保存失败。
  3. 当聊天页面关闭时,聊天记录的数据就会丢失,为什么不在UserMessageController中的onClose方法中判断在关闭聊天框前,集合中是否有聊天记录,如果有则进行保存??因为设置的集合为全局变量,就算是关闭了聊天页面,聊天记录也会暂时保存到集合中,并不会丢失。
效果展示图:

页面展示
实现聊天
数据库信息

完整代码实现如下:
包结构图:

websocket

代码部分:
webSocket配置类:WebSocketConfig.java
package com.example.springboot_websocket.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @author Administrator
 */

@Configuration
@Component
public class WebSocketConfig {
   

    /**
     * 服务器节点
     *
     * 如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
   
        return new ServerEndpointExporter();
    }
}
实体类:UserMessage.java 定义实体类与数据库连接,存储聊天记录
package com.example.springboot_websocket.bean;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * @author Administrator
 */

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserMessage {
   

    /**
     * 消息发送者
     */
    private String username;

    /**
     * 聊天文本
     */
    private String message;

    /**
     * 消息接受者
     */
    private String tousername;

    /**
     * 发送时间
     */
    private Date createtime;
}
mapper层:UserMessageMapper.java
package com.example.springboot_websocket.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springboot_websocket.bean.UserMessage;
import org.apache.ibatis.annotations.Mapper;

/**
 * extends BaseMapper<T>:继承接口即可实现基本的CRUD方法
 * <p>
 * 1.如果自定义的mapper继承了mybatis-plus的BaseMapper时,xxxMapper.xml中不可以包含insert方法,因为在BaseMapper中存在该方法
 * 2.如果对应的xxxMapper.xml中包含insert方法,那么就会执行xxxMapper.xml中的方法,相当于重写BaseMapper中的insert方法;
 * 如果xxxMapper.xml中没有insert方法,默认使用BaseMapper中的方法
 * 3.注意:BaseMapper<T>中的泛型对应相应的实体类
 */

/**
 * @author Administrator
 */

@Mapper
public interface UserMessageMapper extends BaseMapper<UserMessage> {
   

}
service层:UserMessageService.java
package com.example.springboot_websocket.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.springboot_websocket.bean.UserMessage;

/**
 * @author Administrator
 */
public interface UserMessageService extends IService<UserMessage> {
   

}
service层:UserMessageServiceImpl .java
package com.example.springboot_websocket.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springboot_websocket.bean.UserMessage;
import com.example.springboot_websocket.mapper.UserMessageMapper;
import org.springframework.stereotype.Service;

/**
 * @author Administrator
 */

@Service
public class UserMessageServiceImpl extends ServiceImpl<UserMessageMapper, UserMessage> implements UserMessageService {
   

}
controller层:UserMessageController.java
package com.example.springboot_websocket.controller;

import com.alibaba.fastjson.JSON;
import com.example.springboot_websocket.bean.UserMessage;
import com.example.springboot_websocket.service.UserMessageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * websocket类
 *
 * @ServerEndpoint: socket链接地址
 */

/**
 * @author Administrator
 */

@ServerEndpoint("/websocket/{username}")
@Controller
@Component
public class UserMessageController {
   

    /**
     * 设置一次性存储数据的list的长度为固定值,每当list的长度达到固定值时,向数据库存储一次
     */
    private static final Integer LIST_SIZE = 3;

    /**
     * 设置在线人数为静态变量
     */
    public static int onlineNumber = 0;

    private static UserMessageService userMessageService;

    /**
     * 新建list集合存储数据
     */
    private static ArrayList<UserMessage> MessageList = new ArrayList<>();

    /**
     * map(username,websocket)作为对象添加到集合中
     */
    private static Map<String, UserMessageController> clients = new ConcurrentHashMap<String, UserMessageController>();

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * session会话
     */
    private Session session;
    /**
     * 用户名称
     */
    private String username;

    public static synchronized int getOnlineCount() {
   
        return onlineNumber;
    }

    @Autowired
    public void setOgLocationService(UserMessageService userMessageService) {
   
        UserMessageController.userMessageService = userMessageService;
    }

    /**
     * 进入聊天室 --> 项目中读取用户信息获取用户名
     */
    
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值