一、数据库设计
1、表1:user_message
主要用于消息内容的保存,发送方与接收方的信息保存
2、表2:user_message_log
主要用于记录用户的聊天记录以及未读消息个数保存,用于后去聊天用户列表展示与移除,未读消息计数等
二、功能介绍
用户发送消息 :/userapp/message/insertUserMessage
展示用户列表 :/userapp/message/selectUserList (返回用户信息和未读消息的条数)
移除用户列表:/userapp/message/removeUser
用户聊天详细信息:/userapp/message/selectUserMessage
用户撤回消息(三分钟之内可以撤回):/userapp/message/removeUserMessage
(*)、使用定时任务做到用户十分钟未读信息,发送短信提醒
1、用户发送消息 :/userapp/message/insertUserMessage
主要业务代码如下
@Override
public ResultBody insertUserMessage(UserMessageVO messageVO,Integer senderUserId) {
UserMessageDO userMessageDO = new UserMessageDO(messageVO);
if(senderUserId == null){
return ResultBody.success("消息发送失败,请先登录");
}
userMessageDO.setSenderUserId(senderUserId);
if(messageDao.insertUserMessage(userMessageDO) != 0){
UserAccountDO userAccount = userServiceDao.getUserAccountById(userMessageDO.getReceiverUserId());
UserDO userDO = userAccount.buildUserDO();
if(scheduledTaskUtil.check(userDO.getUserAccountId()) == 1){
scheduledTaskUtil.create(userDO);
}
if(messageDao.isUserMessageLog(userMessageDO.getReceiverUserId(), userMessageDO.getSenderUserId()) == null){
UserMessageLogDO userMessageLogDO = new UserMessageLogDO();
userMessageLogDO.setSenderUserId(userMessageDO.getSenderUserId());
userMessageLogDO.setReceiverUserId(userMessageDO.getReceiverUserId());
messageDao.insertUserMessageLog(userMessageLogDO);
}
Integer logId = messageDao.isUserMessageLog(userMessageDO.getSenderUserId(),userMessageDO.getReceiverUserId());
if(logId == null){
UserMessageLogDO userMessageLogDO = new UserMessageLogDO();
userMessageLogDO.setSenderUserId(userMessageDO.getReceiverUserId());
userMessageLogDO.setReceiverUserId(userMessageDO.getSenderUserId());
userMessageLogDO.setMessageCount(1);
messageDao.insertUserMessageLog(userMessageLogDO);
}else {
messageDao.updateUserMessageLog(logId);
}
return ResultBody.success("消息发送成功");
}
return ResultBody.error("消息发送失败");
}
2、展示用户列表 :/userapp/message/selectUserList (返回用户信息和未读消息的条数)
主要业务代码如下
@Override
public ResultBody selectUserList(Integer senderUserId) {
List<UserDO> userAccountDOList = new ArrayList<>();
List<UserMessageLogDO> list = messageDao.selectUserList(senderUserId);
for (UserMessageLogDO userMessageLogDO : list) {
UserAccountDO userAccount = userServiceDao.getUserAccountById(userMessageLogDO.getReceiverUserId());
UserDO userDO = userAccount.buildUserDO();
userDO.setUnreadCount(userMessageLogDO.getMessageCount());
UserMessageDO userMessageDO = messageDao.selectEndUserMessage(userMessageLogDO.getReceiverUserId(), senderUserId);
if(userMessageDO.getContent() != null){
userDO.setEndMessage(userMessageDO.getContent());
}else {
userDO.setEndMessage(userMessageDO.getImgUrl());
}
userDO.setCreateTime(userMessageDO.getCreateTime());
userAccountDOList.add(userDO);
}
// 使用 Collections.sort() 方法和自定义的比较器进行排序
Collections.sort(userAccountDOList, Comparator.comparing(UserDO::getCreateTime).reversed());
return ResultBody.success(userAccountDOList);
}
3、用户聊天详细信息:/userapp/message/selectUserMessage
主要业务代码如下
@Override
public PageResult selectUserMessage(MessageUserQO messageQO,Integer senderUserId) {
scheduledTaskUtil.destroy(senderUserId);
int count = messageDao.countUserMessage(messageQO.getReceiverUserId(),senderUserId);
if (count == 0) {
return PageResult.buildPage(messageQO.getPageNo(), messageQO.getPageSize(), count);
}
Integer pageNo = messageQO.getPageNo();
messageQO.buildCurrentPage();
List<UserMessageDO> messageList = messageDao.selectUserMessage(messageQO,senderUserId);
// Integer logId = messageDao.isUserMessageLog(senderUserId,messageQO.getReceiverUserId());
// if(logId != null){
// messageDao.updateUserMessageCount(logId);
// }
Integer logId2 = messageDao.isUserMessageLog(messageQO.getReceiverUserId(),senderUserId);
if(logId2 != null){
messageDao.updateUserMessageCount(logId2);
}
return PageResult.buildPage(pageNo, messageQO.getPageSize(), count, messageList);
}
<select id="selectUserMessage" resultType="com.mmc.iuav.user.entity.UserMessageDO">
SELECT id, img_url, content, sender_user_id, receiver_user_id, create_time
FROM (
SELECT id, img_url, content, sender_user_id, receiver_user_id, create_time
FROM user_message
WHERE is_deleted = 0 AND sender_user_id IN (#{senderUserId} ,#{messageQO.receiverUserId}) AND receiver_user_id IN (#{senderUserId} ,#{messageQO.receiverUserId})
ORDER BY create_time desc
LIMIT #{messageQO.pageNo},#{messageQO.pageSize}
) AS subquery
ORDER BY create_time ASC;
</select>
4、移除用户列表:/userapp/message/removeUser
主要业务代码如下
@Override
public ResultBody removeMessageByUser(Integer userId, Integer messageId) {
if(messageDao.removeReceiverMessage(userId, messageId) != 0){
return ResultBody.success("删除成功");
}
return ResultBody.error("删除失败");
}
<update id="removeReceiverMessage">
update receiver_message
set is_deleted = 1, deleted_time = NOW()
where user_id = #{userId} and message_id = #{messageId}
</update>
5、用户撤回消息(三分钟之内可以撤回):/userapp/message/removeUserMessage
主要业务代码如下
@Override
public ResultBody removeUserMessage(Integer id) {
UserMessageDO userMessageDO = messageDao.selectUserMessageById(id);
Date createTime = userMessageDO.getCreateTime();
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTime);
if(isOverThreeMinutes(time)){
return ResultBody.error("消息发送已经超过三分钟,撤回失败");
}
if(messageDao.removeUserMessage(id) != 0){
Integer logId = messageDao.isUserMessageLog(userMessageDO.getSenderUserId(),userMessageDO.getReceiverUserId());
if(logId != null){
messageDao.removeUserMessageCount(logId);
}
return ResultBody.success("消息撤回成功已撤回");
}
return ResultBody.error("消息撤回失败");
}
public static boolean isOverThreeMinutes(String createTime) {
// 定义日期时间格式化对象
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 将字符串格式的时间转换为 LocalDateTime 对象
LocalDateTime createDateTime = LocalDateTime.parse(createTime, formatter);
// 计算当前时间与创建时间的时间差(单位:秒)
long secondsDiff = ChronoUnit.SECONDS.between(createDateTime, LocalDateTime.now());
// 如果时间差大于 180 秒(即三分钟),返回 true
return secondsDiff > 180;
}