SMALL
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
채팅 로그 DB 저장
chat.jsp
<jsp:include page="/WEB-INF/views/common/header.jsp">
<jsp:param value="관리자와 1:1채팅" name="title"/>
</jsp:include>
<div class="input-group mb-3">
<input type="text" id="msg" class="form-control" placeholder="관리자에게 보내는 Message">
<div class="input-group-append" style="padding: 0px;">
<button id="sendBtn" class="btn btn-outline-secondary" type="button">Send</button>
</div>
</div>
<div>
<ul class="list-group list-group-flush" id="data"></ul>
</div>
<script>
setTimeout(() => {
stompClient.subscribe(`/app/chat/${chatroomId}`, (message) => {
console.log(`/app/chat/${chatroomId} : `, message);
const {memberId, msg, time} = JSON.parse(message.body);
const li = `
<li class="list-group-item" title="\${time}">\${memberId} : \${msg}</li>
`;
const wrapper = document.querySelector("#data");
wrapper.insertAdjacentHTML('beforeend', li);
});
}, 500);
document.querySelector("#sendBtn").addEventListener('click', (e) => {
const msg = document.querySelector("#msg").value;
if(!msg) return;
const chatlog = {
chatroomId : `${chatroomId}`,
memberId : '<sec:authentication property="principal.username"/>',
msg,
time : Date.now()
};
stompClient.send(`/app/chat/${chatroomId}`, {}, JSON.stringify(chatlog));
// 초기화
document.querySelector("#msg").value = '';
});
</script>
<jsp:include page="/WEB-INF/views/common/footer.jsp"/>
Controller
StompController
@Autowired
ChatService chatService;
@MessageMapping("/chat/{chatroomId}")
@SendTo("/app/chat/{chatroomId}")
public ChatLog chatLog(@RequestBody ChatLog chatlog) {
log.debug("chatlog = {}", chatlog);
int result = chatService.insertChatLog(chatlog);
return chatlog;
}
MessageMapping으로 받아서 DB insert 처리 후 다시 '/app/chat/chatroomId'로 넘겨주었습니다.
Service (interface 생략)
ChatServiceImpl
@Override
public int insertChatLog(ChatLog chatlog) {
return chatDao.insertChatLog(chatlog);
}
Dao
ChatDao interface
@Insert("insert into chat_log values(seq_chat_log_no.nextval, #{chatroomId}, #{memberId}, #{msg}, #{time})")
int insertChatLog(ChatLog chatlog);
하지만 자꾸 채팅로그가 2개씩 나오는 것을 확인할 수 있습니다.
이를 해결해보겠습니다.
네트워크를 확인해보면, content-type이 있고/없고에 대한 차이가 있는 것을 확인할 수 있습니다.
분기처리를 통해 한 번만 출력되도록 하겠습니다.
setTimeout(() => {
stompClient.subscribe(`/app/chat/${chatroomId}`, (message) => {
const {'content-type':contentType} = message.headers;
if(!contentType) {
console.log(`/app/chat/${chatroomId} : `, message);
const {memberId, msg, time} = JSON.parse(message.body);
const li = `
<li class="list-group-item" title="\${time}">\${memberId} : \${msg}</li>
`;
const wrapper = document.querySelector("#data");
wrapper.insertAdjacentHTML('beforeend', li);
}
});
}, 500);
한 번만 출력되는 것을 확인할 수 있습니다.
기존 채팅 내역 불러오기
- 기존 채팅 내역이 있다면, 그대로 가져와 보여줘야 함
Controller
ChatController
@GetMapping("/chat.do")
public void chat(Authentication authentication, Model model) {
// 1. 채팅방 유무 조회
Member loginMember = (Member)authentication.getPrincipal();
ChatMember chatMember = chatService.findChatMemberByMemberId(loginMember.getMemberId());
log.debug("chatMember = {}", chatMember);
String chatroomId = null;
if(chatMember == null) {
// 처음 입장한 경우
chatroomId = generateChatroomId();
log.debug("chatroomId = {}", chatroomId);
// chatmember insert 2행! (관리자/로그인회원)
List<ChatMember> chatMembers = Arrays.asList(
new ChatMember(chatroomId, loginMember.getMemberId()),
new ChatMember(chatroomId, "admin") // ROLE로 admin을 구별하지만, 일단 'admin' 아이디로 고정!
);
chatService.insertChatMembers(chatMembers);
} else {
// 재입장한 경우
chatroomId = chatMember.getChatroomId();
List<ChatLog> chatLogs = chatService.findChatlogByChatroomId(chatroomId);
log.debug("chatLogs = {}", chatLogs);
model.addAttribute("chatLogs", chatLogs);
}
model.addAttribute("chatroomId", chatroomId);
}
Service interface 생략
ChatServiceImpl
@Override
public List<ChatLog> findChatlogByChatroomId(String chatroomId) {
return chatDao.findChatlogByChatroomId(chatroomId);
}
Dao
ChatDao interface
@Select("select * from chat_log where chatroom_id = #{chatroomId} order by no")
List<ChatLog> findChatlogByChatroomId(String chatroomId);
chat.jsp
<div class="input-group mb-3">
<input type="text" id="msg" class="form-control" placeholder="관리자에게 보내는 Message">
<div class="input-group-append" style="padding: 0px;">
<button id="sendBtn" class="btn btn-outline-secondary" type="button">Send</button>
</div>
</div>
<div>
<ul class="list-group list-group-flush" id="data">
<c:if test="${not empty chatLogs}">
<c:forEach items="${chatLogs}" var="log">
<%
ChatLog chat = (ChatLog) pageContext.getAttribute("log");
String time = new Date(chat.getTime()).toString();
%>
<li class="list-group-item" title="<%= time %>">${log.memberId} : ${log.msg}</li>
</c:forEach>
</c:if>
</ul>
</div>
LIST
'Java > Spring' 카테고리의 다른 글
Spring) 관리자 1:1 채팅 - 관리자 (채팅 목록 랜더링, 회원 별 채팅창 팝업, 채팅 보내기, 끌어올리기 처리) (2) | 2022.10.11 |
---|---|
Spring) 관리자와 1:1 채팅 - 기본 흐름, 구독 처리 (0) | 2022.10.10 |
Spring) Web-Socket - Stomp (게시글 조회 알림 구현) (0) | 2022.09.15 |
Spring) Web-Socket - Stomp (전체/개별 공지사항 전송 구현) (0) | 2022.09.15 |
Spring) Spring-WebSocket - Stomp, Stomp 환경설정 및 흐름파악 (0) | 2022.09.14 |