반응형
이전 단계에서 모든 처리를 마치고 이제 메시지만 전송해주면된다.
그런데 메시지를 전송할때 수신자가 현재 웹소켓에 연결되어있지않을때에 대한 처리를 해주어야했다.
getOnlineSession
private List<WebSocketSession> getOnlineSession(List<UserEntity> userEntities) {
return userEntities.stream()
.map(receiver -> userSessionMap.get(receiver.getEmail()))
.filter(Objects::nonNull)
.toList();
}
getOfflineUsers
private List<UserEntity> getOfflineUsers(List<UserEntity> userEntities) {
List<UserEntity> offlineReceivers = userEntities.stream()
.filter(receiver -> userSessionMap.get(receiver.getEmail()) == null)
.toList();
return offlineReceivers;
}
위 메서드를 이용해서 온라인인 유저는 세션으로 받아오고, 오프라인인 유저도 찾았다.
private void sendMessageAndkeep(List<UserEntity> userEntities, ChatMessageDto chatMessageDto, UserEntity sender) {
//연결중인 세션만 찾아서 문자를전송
getOnlineSession(userEntities).forEach(
receiverSession -> sendMessage(receiverSession, chatMessageDto.getMessage()));
//연결중이지않은 유저는 해당 기록을 저장.
saveOfflineChat(userEntities, chatMessageDto, sender);
}
연결되어있는세션은 바로 chatMessegeDto에있는 message를 전송해주고
연결중이지않은 유저는 유저정보와 메시지를 저장해준다.
saveOfflineChat
private void saveOfflineChat(List<UserEntity> userEntities, ChatMessageDto chatMessageDto, UserEntity sender) {
List<UserEntity> offlineReceivers = getOfflineUsers(userEntities);
offlineReceivers.forEach(offlineUser -> {
OfflineChatHistoryEntity offlineChat = OfflineChatHistoryEntity.builder()
.senderId(sender.getId())
.receiverId(offlineUser.getId())
.content(chatMessageDto.getMessage())
.createdAt(LocalDateTime.now())
.build();
offlineChatHistoryRepository.save(offlineChat);
});
}
이렇게 전송되지못한메시지는 저장해두었다가 이후에 해당유저가 웹소켓에 연결될때 다시 전송해준다.
웹소켓에 연결될때 실행되는 afterConnectionEstablished 메서드에 해당 기능을 추가해준다.
@Override
@Transactional
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//유저의 이메일을 얻어온다.
String userId = getUserId(session);
UserEntity userEntity = userRepository.findByEmail(userId)
.orElseThrow(() -> new ApiException(ErrorCode.BAD_REQUEST, "없는 유저입니다."));
// 오프라인 유저 리스트에 해당 유저가 있는지 확인
if (offlineChatHistoryRepository.existsByReceiverId(userEntity.getId())) {
// chatRepository에서 해당 유저의 오프라인 메시지 정보 조회
List<OfflineChatHistoryEntity> offlineMessages = offlineChatHistoryRepository.findByReceiverId(
userEntity.getId());
// 조회한 메시지 정보를 새로 연결된 세션을 통해 전송
for (OfflineChatHistoryEntity message : offlineMessages) {
sendMessage(session, message.getContent());
}
// 오프라인 유저 리스트에서 해당 유저 제거
offlineChatHistoryRepository.deleteAllByReceiverId(userEntity.getId());
}
//유저의 이메일과 세션을 매핑해서 서버에서 관리.
userSessionMap.put(userId, session);
log.info("{} 환영합니다", userId);
}
이렇게 해주면 웹소켓에 연결될때 받지못한 메시지를 받을수있다.
반응형
'공부 임시 저장소' 카테고리의 다른 글
스프링 부트 - spring-security-jwt (0) | 2024.06.25 |
---|---|
스프링부트 - aws s3파일저장 (0) | 2024.06.25 |
스프링부트 - 파일 저장 (0) | 2024.06.24 |
사이드 프로젝트) 채팅앱 (0) | 2024.06.24 |
스프링 웹소켓 (1) | 2024.06.03 |