feature: 新增所有消息的list接口

This commit is contained in:
乾乾
2025-07-15 11:55:00 +08:00
parent f1be51ea36
commit 9d52805116
15 changed files with 155 additions and 4 deletions
@@ -75,7 +75,7 @@ public class RedisConfig {
config.useSingleServer()
.setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort())
// redis 6.x 需要设置用户名
// .setUsername("default")
.setUsername("default")
// 记得打开密码设置
.setPassword(redisProperties.getPassword())
// .setPassword(null)
@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
@@ -49,6 +50,16 @@ public class ChatController {
return ApiResult.success(msgPage);
}
@GetMapping("/msg/list")
@Operation(summary ="消息列表")
// @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP)
public ApiResult<List<ChatMessageResp>> getMsgPage() {
List<ChatMessageResp> msgPage = chatService.getMsgList(RequestHolder.get().getUid());
Set<String> blackMembers = getBlackUidSet();
msgPage.removeIf(a -> blackMembers.contains(a.getFromUser().getUid().toString()));
return ApiResult.success(msgPage);
}
private void filterBlackMsg(CursorPageBaseResp<ChatMessageResp> memberPage) {
Set<String> blackMembers = getBlackUidSet();
memberPage.getList().removeIf(a -> blackMembers.contains(a.getFromUser().getUid().toString()));
@@ -15,6 +15,7 @@ import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* <p>
@@ -136,4 +137,8 @@ public class ContactDao extends ServiceImpl<ContactMapper, Contact> {
return update(new UpdateWrapper<Contact>().lambda()
.eq(Contact::getRoomId, roomId).eq(Contact::getUid, uid).set(Contact::getHide, hide));
}
public Map<Long, Long> getLastMsgIds(Long receiveUid, List<Long> roomIds) {
return baseMapper.getLastMsgIds(receiveUid, roomIds);
}
}
@@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
@@ -84,4 +85,9 @@ public class MessageDao extends ServiceImpl<MessageMapper, Message> {
}
return this.update(wrapper);
}
public List<Message> getMessagesByRoomIds(List<Long> roomIds, Map<Long, Long> lastMsgIds) {
return baseMapper.selectMessagesByRoomIds(roomIds, lastMsgIds);
}
}
@@ -6,6 +6,7 @@ import com.hula.core.chat.mapper.RoomGroupMapper;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
@@ -38,4 +39,10 @@ public class RoomGroupDao extends ServiceImpl<RoomGroupMapper, RoomGroup> {
.like(RoomGroup::getAccount, account)
.list();
}
public List<Long> getRoomIdByGroupId(List<Long> groupIds) {
return lambdaQuery()
.like(RoomGroup::getId, groupIds)
.list().stream().map(RoomGroup::getRoomId).collect(Collectors.toList());
}
}
@@ -2,10 +2,12 @@ package com.hula.core.chat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hula.core.chat.domain.entity.Contact;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* <p>
@@ -18,4 +20,6 @@ public interface ContactMapper extends BaseMapper<Contact> {
void refreshOrCreateActiveTime(@Param("roomId") Long roomId, @Param("memberUidList") List<Long> memberUidList, @Param("msgId") Long msgId, @Param("activeTime") Date activeTime);
@MapKey("room_id")
Map<Long, Long> getLastMsgIds(@Param("roomId")Long receiveUid, @Param("roomIds") List<Long> roomIds);
}
@@ -2,7 +2,11 @@ package com.hula.core.chat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hula.core.chat.domain.entity.Message;
import com.hula.core.chat.domain.entity.Message;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* <p>
@@ -13,4 +17,15 @@ import com.hula.core.chat.domain.entity.Message;
*/
public interface MessageMapper extends BaseMapper<Message> {
@Select({
"<script>",
"SELECT * FROM message WHERE room_id IN",
"<foreach item='roomId' collection='roomIds' open='(' separator=',' close=')'>",
"#{roomId}",
"</foreach>",
"AND id > COALESCE(#{lastMsgIds[roomId]}, 0)",
"ORDER BY create_time DESC",
"</script>"
})
List<Message> selectMessagesByRoomIds(@Param("roomIds") List<Long> roomIds, @Param("lastMsgIds") Map<Long, Long> lastMsgIds);
}
@@ -58,6 +58,8 @@ public interface ChatService {
*/
CursorPageBaseResp<ChatMessageResp> getMsgPage(ChatMessagePageReq request, @Nullable Long receiveUid);
List<ChatMessageResp> getMsgList(Long receiveUid);
ChatMemberStatisticResp getMemberStatistic();
void setMsgMark(Long uid, ChatMessageMarkReq request);
@@ -26,4 +26,6 @@ public interface ContactService {
Integer getMsgUnReadCount(Message message);
Map<Long, MsgReadInfoDTO> getMsgReadInfo(List<Message> messages);
Map<Long, Long> getLastMsgIds(Long receiveUid, List<Long> roomIds);
}
@@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 群成员相关缓存
@@ -97,4 +98,10 @@ public class GroupMemberCache {
public List<Long> evictMemberList(Long roomId) {
return null;
}
public List<Long> getJoinedRoomIds(Long uid) {
List<Long> groupIds = groupMemberDao.getBaseMapper().selectList(new QueryWrapper<GroupMember>().eq("uid", uid)).stream().map(GroupMember::getGroupId).collect(Collectors.toList());
return roomGroupDao.getRoomIdByGroupId(groupIds);
}
}
@@ -28,6 +28,7 @@ import com.hula.core.chat.service.ContactService;
import com.hula.core.chat.service.adapter.MemberAdapter;
import com.hula.core.chat.service.adapter.MessageAdapter;
import com.hula.core.chat.service.adapter.RoomAdapter;
import com.hula.core.chat.service.cache.GroupMemberCache;
import com.hula.core.chat.service.cache.RoomCache;
import com.hula.core.chat.service.cache.RoomGroupCache;
import com.hula.core.chat.service.helper.ChatMemberHelper;
@@ -61,6 +62,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.hula.common.config.ThreadPoolConfig.HULA_EXECUTOR;
@@ -78,8 +80,9 @@ public class ChatServiceImpl implements ChatService {
private final RoomDao roomDao;
private final UserFriendDao userFriendDao;
private final RoomGroupDao roomGroupDao;
private final GroupMemberCache groupMemberCache;
private MessageDao messageDao;
private MessageDao messageDao;
private UserDao userDao;
private ApplicationEventPublisher applicationEventPublisher;
private UserCache userCache;
@@ -235,7 +238,42 @@ public class ChatServiceImpl implements ChatService {
return CursorPageBaseResp.init(cursorPage, getMsgRespBatch(request.getRoomId(), cursorPage.getList(), receiveUid), cursorPage.getTotal());
}
private Long getLastMsgId(Long roomId, Long receiveUid) {
// @Cacheable(value = "userRooms", key = "#uid", unless = "#result == null")
public List<Long> getAccessibleRoomIds(Long uid) {
// 从群成员缓存和好友关系表中获取有效房间ID
List<Long> groupRoomIds = groupMemberCache.getJoinedRoomIds(uid);
List<Long> friendRoomIds = userFriendDao.getAllRoomIdsByUid(uid);
return Stream.concat(groupRoomIds.stream(), friendRoomIds.stream()).distinct().collect(Collectors.toList());
}
@Override
public List<ChatMessageResp> getMsgList(Long receiveUid) {
// 1. 获取用户所有未屏蔽的聊天室ID列表
List<Long> roomIds = getAccessibleRoomIds(receiveUid);
if (CollectionUtil.isEmpty(roomIds)) {
return Collections.emptyList();
}
// 2. 批量查询所有房间的最后一条消息ID(用于权限过滤)
Map<Long, Long> lastMsgIds = contactService.getLastMsgIds(receiveUid, roomIds);
// 3. 批量查询所有符合条件的消息
List<Message> messages = messageDao.getMessagesByRoomIds(roomIds, lastMsgIds);
Map<Long, List<Message>> messageMap = messages.stream()
.filter(message -> message.getRoomId() != null)
.collect(Collectors.groupingBy(Message::getRoomId, LinkedHashMap::new, Collectors.toList()));
// 4. 转换为响应对象并返回
List<ChatMessageResp> baseMessages = new ArrayList<>();
for (Long roomId : messageMap.keySet()) {
baseMessages.addAll(getMsgRespBatch(roomId, messageMap.get(roomId), receiveUid));
}
return baseMessages;
}
private Long getLastMsgId(Long roomId, Long receiveUid) {
Room room = roomCache.get(roomId);
AssertUtil.isNotEmpty(room, "房间号有误");
if (room.isHotRoom()) {
@@ -61,4 +61,9 @@ public class ContactServiceImpl implements ContactService {
return readInfoDTO;
}).collect(Collectors.toMap(MsgReadInfoDTO::getMsgId, Function.identity()));
}
@Override
public Map<Long, Long> getLastMsgIds(Long receiveUid, List<Long> roomIds) {
return contactDao.getLastMsgIds(receiveUid, roomIds);
}
}
@@ -158,4 +158,10 @@ public class UserFriendDao extends ServiceImpl<UserFriendMapper, UserFriend> {
@CacheEvict(cacheNames = "userFriend", key = "'room:'+#roomId+':uid:'+#uid")
public void evictFriendCache(Long roomId, Long uid) {
}
public List<Long> getAllRoomIdsByUid(Long uid) {
return lambdaQuery()
.eq(UserFriend::getUid, uid)
.list().stream().map(UserFriend::getRoomId).collect(Collectors.toList());
}
}
@@ -13,4 +13,13 @@
`last_msg_id`=VALUES(last_msg_id),
`active_time`=VALUES(active_time)
</insert>
<select id="getLastMsgIds">
SELECT room_id, MAX(last_msg_id) AS last_msg_id
FROM contact
WHERE room_id IN
<foreach item="roomId" collection="roomIds" open="(" separator="," close=")">
#{roomId}
</foreach> AND shield = 0 GROUP BY room_id
</select>
</mapper>
@@ -3,6 +3,7 @@ package com.hula.common;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hula.HuLaImServiceApplication;
import com.hula.core.chat.dao.ContactDao;
import com.hula.core.chat.dao.RoomFriendDao;
import com.hula.core.chat.dao.RoomGroupDao;
import com.hula.core.chat.domain.entity.Contact;
import com.hula.core.chat.domain.entity.Room;
@@ -13,18 +14,24 @@ import com.hula.core.chat.service.cache.GroupMemberCache;
import com.hula.core.chat.service.cache.RoomCache;
import com.hula.core.chat.service.cache.RoomFriendCache;
import com.hula.core.user.dao.UserDao;
import com.hula.core.user.dao.UserFriendDao;
import com.hula.core.user.domain.entity.User;
import com.hula.core.user.domain.entity.UserFriend;
import com.hula.snowflake.uid.UidGenerator;
import com.hula.snowflake.uid.utils.Base62Encoder;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static com.hula.core.chat.service.adapter.ChatAdapter.SEPARATOR;
@SpringBootTest(classes = HuLaImServiceApplication.class)
@@ -43,12 +50,16 @@ public class CreateAccount {
@Resource
private RoomCache roomCache;
@Resource
private UserFriendDao userFriendDao;
@Resource
private RoomFriendCache roomFriendCache;
@Resource
private GroupMemberCache groupMemberCache;
@Autowired
private RoomFriendDao roomFriendDao;
/**
* 移除不存在的会话
@@ -80,6 +91,29 @@ public class CreateAccount {
System.out.println("需要移除的会话:" + ids);
}
@Test
public void syncRoomId() {
List<UserFriend> list = userFriendDao.list();
for (UserFriend userFriend : list) {
ArrayList<Long> uidList = new ArrayList<>();
uidList.add(userFriend.getUid());
uidList.add(userFriend.getFriendUid());
RoomFriend roomFriend = new RoomFriend();
roomFriend.setRoomKey(uidList.stream()
.sorted()
.map(String::valueOf)
.collect(Collectors.joining(SEPARATOR)));
RoomFriend friend = roomFriendDao.getByKey(roomFriend.getRoomKey());
UserFriend userFriendDb = new UserFriend();
userFriendDb.setId(userFriend.getId());
userFriendDb.setRoomId(friend.getRoomId());
userFriendDao.updateById(userFriendDb);
}
}
/**
* 批量填充群账号