일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- map
- Properties
- alter
- NIO
- deque
- html
- Java
- BFS
- 힙덤프
- scanner
- set
- 스택
- 리소스모니터링
- sql
- string
- JPA
- priority_queue
- math
- Calendar
- CSS
- 큐
- List
- union_find
- 스프링부트
- javascript
- GC로그수집
- spring boot
- date
- dfs
- Union-find
- Today
- Total
매일 조금씩
Spring MVC 로 메세지 기능 구현 본문
다른 사람 프로필 사진을 누르면 그 사람의 프로필 페이지로 이동이된다.
다른 사람 프로필 페이지에선 최초로 쪽지를 보낼수 있고, 쪽지함에서 쪽지를 보낼수도 있다.
다만, 새로운 메세지가 왔을 때 실시간으로 바로 반영이 되지 않고, 새로고침이 실행될때 반영이 되기때문에
몇초마다 페이지 전체 혹은 일부가 리로드 되는 코드를 추가해야한다.
*** 순서 ***
1. 구현 완료 모습
2. DB 테이블 구축
3. 코드
3-1. JSP
3-2. Controller
3-3. DAO
3-4. TO
3-5. SQL(mapper)
1. 구현 완료 모습
1) 다른 사람 프로필에서 메세지 보내기
2) 메세지함에서 메세지 보내기
2. DB 테이블 구축
#######메세지 관련 DDL#########
create table message(
no int auto_increment primary key,
room int not null,
send_nick varchar(50) not null,
recv_nick varchar(50) not null,
send_time datetime not null,
read_time datetime not null,
content varchar(1000) not null,
read_chk int not null,
constraint m_send_nick_fk foreign key(send_nick) references user(nick)
on delete cascade on update cascade,
constraint m_recv_nick_fk foreign key(recv_nick) references user(nick)
on delete cascade on update cascade
);
순번 | 컬럼명 | 컬럼설명 | 데이터 타입 | Null여부 | 제약조건 |
0 | no | 메세지 번호 | int | pk auto_increment |
|
1 | room | 메세지 방 번호 | int | not null | |
2 | send_nick | 메세지 보내는 사람 nick | varchar(50) | not null | fk references user(nick) on delete cascade on update cascade |
3 | recv_nick | 메세지 받는 사람 nick | varchar(50) | not null | fk references user(nick) on delete cascade on update cascade |
4 | send_time | 메세지 보낸 시간 | datetime | not null | |
5 | read_time | 메세지 읽은 시간 | datetime | not null | |
6 | content | 메세지 내용 | varchar(1000) | not null | |
7 | read_chk | 받는사람이 메세지 읽었는지 체크 안읽었으면1, 읽었으면 0 |
int | not null |
foreign key인 send_nick과 recv_nick에 대해 제약조건을 걸었다.
1. 보낸사람(send_nick) 제약조건 m_send_nick_fk
- 보낸사람이 삭제되면(탈퇴) 메세지도 사라진다. on delete cascade
- 보낸사람의 닉네임이 수정되면 send_nick도 수정된다. on update cascade
2. 받는사람(recv_nick) 제약조건 m_recv_nick_fk
- 받는사람이 삭제되면(탈퇴) 메세지도 사라진다. on delete cascade
- 받는사람의 닉네임이 수정되면 recv_nick도 수정된다. on update cascade
3. 코드
3-1. JSP
- message_list.jsp : 메세지함 페이지 html로 메인 html
- message_ajax_list.jsp : 메세지함의 메세지 리스트부분 html (메세지함 페이지에 동적으로 삽입됨)
- message_content_list.jsp : 메세지 내용 부분 html (메세지함 페이지에서 메세지 리스트 중 하나가 클릭되면 삽입됨)
1) message_list.jsp
> view > message > message_list.jsp
메세지함의 메인 html이라고 보면 된다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Want 사진자랑하기</title>
<jsp:include page="../include/index.jsp"></jsp:include>
<!-- CSS File -->
<link href="./resources/css/message_list.css" rel="stylesheet">
<link href="./resources/css/navbar.css" rel="stylesheet">
<!-- 메세지 전송 아이콘(종이비행기) 때문에 필요 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<!-- 메뉴바
현재페이지 뭔지 param.thisPage에 넣어서 navbar.jsp에 던짐 -->
<jsp:include page="../include/navbar.jsp">
<jsp:param value="message" name="thisPage" />
</jsp:include>
<br />
<br />
<br />
<br />
<br />
<div class="msg-container">
<div class="messaging">
<div class="inbox_msg">
<!-- 메세지 목록 영역 -->
<div class="inbox_people">
<div class="headind_srch">
<div class="recent_heading">
<h4>Recent</h4>
</div>
<!-- 메세지 검색 -->
<div class="srch_bar">
<div class="stylish-input-group">
<input type="text" class="search-bar" placeholder="Search" >
<span class="input-group-addon">
<button type="button"> <i class="fa fa-search" aria-hidden="true"></i> </button>
</span>
</div>
</div>
</div>
<!-- 메세지 리스트 -->
<div class="inbox_chat">
</div>
</div>
<!-- 메세지 내용 영역 -->
<div class="mesgs">
<!-- 메세지 내용 목록 -->
<div class="msg_history" name="contentList">
<!-- 메세지 내용이 올 자리 -->
</div>
<div class="send_message">
</div>
<!-- 메세지 입력란이 올자리 -->
</div>
</div>
</div>
</div>
<script>
// 가장 처음 메세지 리스트를 가져온다.
const FirstMessageList = function(){
$.ajax({
url:"message_ajax_list.do",
method:"get",
data:{
},
success:function(data){
console.log("메세지 리스트 리로드 성공");
$('.inbox_chat').html(data);
// 메세지 리스트중 하나를 클릭했을 때
$('.chat_list').on('click', function(){
//alert('room : '+ $(this).attr('room'));
let room = $(this).attr('room');
let other_nick = $(this).attr('other-nick');
// 선택한 메세지빼고 나머지는 active 효과 해제하기
$('.chat_list_box').not('.chat_list_box.chat_list_box'+room).removeClass('active_chat');
// 선택한 메세지만 active 효과 주기
$('.chat_list_box'+room).addClass('active_chat');
let send_msg = "";
send_msg += "<div class='type_msg'>";
send_msg += " <div class='input_msg_write row'>";
send_msg += " <div class='col-11'>";
send_msg += " <input type='text' class='write_msg form-control' placeholder='메세지를 입력...' />";
send_msg += " </div>";
send_msg += " <div class='col-1'>";
send_msg += " <button class='msg_send_btn' type='button'><i class='fa fa-paper-plane-o' aria-hidden='true'></i></button>";
send_msg += " </div>";
send_msg += " </div>";
send_msg += "</div>";
// 메세지 입력, 전송 칸을 보인다.
$('.send_message').html(send_msg);
// 메세지 전송버튼을 눌렀을 때
$('.msg_send_btn').on('click',function(){
// 메세지 전송 함수 호출
SendMessage(room, other_nick);
// 전송버튼을 누르면 메세지 리스트가 리로드 되면서 현재 열린 메세지의 선택됨 표시가 사라진다.
// 이걸 해결하기 위해 메세지 전송버튼을 누르고 메세지 리스트가 리로드되면 메세지 리스트의 첫번째 메세지(현재 열린 메세지)가 선택됨 표시 되도록 한다.
//$('.chat_list_box:first').addClass('active_chat');
});
// 메세지 내용을 불러오는 함수 호출
MessageContentList(room);
});
}
})
};
// 메세지 리스트를 다시 가져온다.
const MessageList = function(){
$.ajax({
url:"message_ajax_list.do",
method:"get",
data:{
},
success:function(data){
console.log("메세지 리스트 리로드 성공");
$('.inbox_chat').html(data);
// 메세지 리스트중 하나를 클릭했을 때
$('.chat_list').on('click', function(){
//alert('room : '+ $(this).attr('room'));
let room = $(this).attr('room');
let other_nick = $(this).attr('other-nick');
// 선택한 메세지빼고 나머지는 active 효과 해제하기
$('.chat_list_box').not('.chat_list_box.chat_list_box'+room).removeClass('active_chat');
// 선택한 메세지만 active 효과 주기
$('.chat_list_box'+room).addClass('active_chat');
let send_msg = "";
send_msg += "<div class='type_msg'>";
send_msg += " <div class='input_msg_write row'>";
send_msg += " <div class='col-11'>";
send_msg += " <input type='text' class='write_msg form-control' placeholder='메세지를 입력...' />";
send_msg += " </div>";
send_msg += " <div class='col-1'>";
send_msg += " <button class='msg_send_btn' type='button'><i class='fa fa-paper-plane-o' aria-hidden='true'></i></button>";
send_msg += " </div>";
send_msg += " </div>";
send_msg += "</div>";
// 메세지 입력, 전송 칸을 보인다.
$('.send_message').html(send_msg);
// 메세지 전송버튼을 눌렀을 때
$('.msg_send_btn').on('click',function(){
// 메세지 전송 함수 호출
SendMessage(room, other_nick);
// 전송버튼을 누르면 메세지 리스트가 리로드 되면서 현재 열린 메세지의 선택됨 표시가 사라진다.
// 이걸 해결하기 위해 메세지 전송버튼을 누르고 메세지 리스트가 리로드되면 메세지 리스트의 첫번째 메세지(현재 열린 메세지)가 선택됨 표시 되도록 한다.
//$('.chat_list_box:first').addClass('active_chat');
});
// 메세지 내용을 불러오는 함수 호출
MessageContentList(room);
});
// 전송버튼을 누르면 메세지 리스트가 리로드 되면서 현재 열린 메세지의 선택됨 표시가 사라진다.
// 이걸 해결하기 위해 메세지 전송버튼을 누르고 메세지 리스트가 리로드되면 메세지 리스트의 첫번째 메세지(현재 열린 메세지)가 선택됨 표시 되도록 한다.
$('.chat_list_box:first').addClass('active_chat');
}
})
};
// 메세지 내용을 가져온다.
// 읽지 않은 메세지들을 읽음으로 바꾼다.
const MessageContentList = function(room) {
$.ajax({
url:"message_content_list.do",
method:"GET",
data:{
room : room,
},
success:function(data){
console.log("메세지 내용 가져오기 성공");
// 메세지 내용을 html에 넣는다
$('.msg_history').html(data);
// 이 함수로 메세지 내용을 가져올때마다 스크롤를 맨아래로 가게 한다.
$(".msg_history").scrollTop($(".msg_history")[0].scrollHeight);
},
error : function() {
alert('서버 에러');
}
})
$('.unread'+room).empty();
};
// 메세지를 전송하는 함수
const SendMessage = function(room, other_nick){
let content = $('.write_msg').val();
//alert("content: " + content);
content = content.trim();
if(content == ""){
alert("메세지를 입력하세요!");
}else{
$.ajax({
url:"message_send_inlist.do",
method:"GET",
data:{
room : room,
other_nick: other_nick,
content: content
},
success:function(data){
console.log("메세지 전송 성공");
// 메세지 입력칸 비우기
$('.write_msg').val("");
// 메세지 내용 리로드
MessageContentList(room);
// 메세지 리스트 리로드
MessageList();
},
error : function() {
alert('서버 에러');
}
});
}
};
$(document).ready(function(){
// 메세지 리스트 리로드
FirstMessageList();
});
</script>
</body>
</html>
[설명]
실행되는 순서에 따라 코드를 설명한다.
▶ 메세지 리스트(message_ajax_list.jsp) 불러오기
메세지함 페이지가 처음에 열리거나 리로드되면 메세지 리스트(message_ajax_list.jsp) 코드를 가져와서 해당 부분에 삽입한다.
아래는 메세지 리스트가 삽입되는 부분이다.
<!-- 메세지 리스트 -->
<div class="inbox_chat">
(메세지 리스트)
</div>
메세지함 페이지가 열리거나 리로드되면 아래처럼 FirstMessageList()를 호출해서 메세지를 가져온다.
$(document).ready(function(){
// 메세지 리스트 리로드
FirstMessageList();
});
FirstMessageList 함수이다.
// 가장 처음 메세지 리스트를 가져온다.
const FirstMessageList = function(){
$.ajax({
url:"message_ajax_list.do",
method:"get",
data:{
},
success:function(data){
console.log("메세지 리스트 리로드 성공");
$('.inbox_chat').html(data);
// 메세지 리스트중 하나를 클릭했을 때
$('.chat_list').on('click', function(){
//alert('room : '+ $(this).attr('room'));
let room = $(this).attr('room');
let other_nick = $(this).attr('other-nick');
// 선택한 메세지빼고 나머지는 active 효과 해제하기
$('.chat_list_box').not('.chat_list_box.chat_list_box'+room).removeClass('active_chat');
// 선택한 메세지만 active 효과 주기
$('.chat_list_box'+room).addClass('active_chat');
let send_msg = "";
send_msg += "<div class='type_msg'>";
send_msg += " <div class='input_msg_write row'>";
send_msg += " <div class='col-11'>";
send_msg += " <input type='text' class='write_msg form-control' placeholder='메세지를 입력...' />";
send_msg += " </div>";
send_msg += " <div class='col-1'>";
send_msg += " <button class='msg_send_btn' type='button'><i class='fa fa-paper-plane-o' aria-hidden='true'></i></button>";
send_msg += " </div>";
send_msg += " </div>";
send_msg += "</div>";
// 메세지 입력, 전송 칸을 보인다.
$('.send_message').html(send_msg);
// 메세지 전송버튼을 눌렀을 때
$('.msg_send_btn').on('click',function(){
// 메세지 전송 함수 호출
SendMessage(room, other_nick);
// 전송버튼을 누르면 메세지 리스트가 리로드 되면서 현재 열린 메세지의 선택됨 표시가 사라진다.
// 이걸 해결하기 위해 메세지 전송버튼을 누르고 메세지 리스트가 리로드되면 메세지 리스트의 첫번째 메세지(현재 열린 메세지)가 선택됨 표시 되도록 한다.
//$('.chat_list_box:first').addClass('active_chat');
});
// 메세지 내용을 불러오는 함수 호출
MessageContentList(room);
});
}
})
};
위 함수에서 아래 코드를 통해 가져온 메세지 리스트 코드가 삽입된다.
$('.inbox_chat').html(data);
▶ 메세지 내용(message_content_list.jsp) 보기
메세지 리스트에서 하나를 클릭하면 메세지 내용(message_content_list.jsp)을 볼수 있다.
아래는 메세지 내용이 삽입되는 부분이다.
<!-- 메세지 내용 영역 -->
<div class="mesgs">
<!-- 메세지 내용 목록 -->
<div class="msg_history" name="contentList">
<!-- 메세지 내용이 올 자리 -->
</div>
<div class="send_message">
</div>
<!-- 메세지 입력란이 올자리 -->
</div>
아래는 메세지 리스트에서 하나를 클릭했을때의 이벤트 처리 부분이다.
MessageContentList 함수를 호출해서 메세지 내용 코드를 가져온다.
// 메세지 리스트중 하나를 클릭했을 때
$('.chat_list').on('click', function(){
//alert('room : '+ $(this).attr('room'));
let room = $(this).attr('room');
let other_nick = $(this).attr('other-nick');
// 선택한 메세지빼고 나머지는 active 효과 해제하기
$('.chat_list_box').not('.chat_list_box.chat_list_box'+room).removeClass('active_chat');
// 선택한 메세지만 active 효과 주기
$('.chat_list_box'+room).addClass('active_chat');
let send_msg = "";
send_msg += "<div class='type_msg'>";
send_msg += " <div class='input_msg_write row'>";
send_msg += " <div class='col-11'>";
send_msg += " <input type='text' class='write_msg form-control' placeholder='메세지를 입력...' />";
send_msg += " </div>";
send_msg += " <div class='col-1'>";
send_msg += " <button class='msg_send_btn' type='button'><i class='fa fa-paper-plane-o' aria-hidden='true'></i></button>";
send_msg += " </div>";
send_msg += " </div>";
send_msg += "</div>";
// 메세지 입력, 전송 칸을 보인다.
$('.send_message').html(send_msg);
// 메세지 전송버튼을 눌렀을 때
$('.msg_send_btn').on('click',function(){
// 메세지 전송 함수 호출
SendMessage(room, other_nick);
// 전송버튼을 누르면 메세지 리스트가 리로드 되면서 현재 열린 메세지의 선택됨 표시가 사라진다.
// 이걸 해결하기 위해 메세지 전송버튼을 누르고 메세지 리스트가 리로드되면 메세지 리스트의 첫번째 메세지(현재 열린 메세지)가 선택됨 표시 되도록 한다.
//$('.chat_list_box:first').addClass('active_chat');
});
// 메세지 내용을 불러오는 함수 호출
MessageContentList(room);
});
아래는 메세지 내용을 가져오는 함수인 MessageContentList 함수이다.
// 읽지 않은 메세지들을 읽음으로 바꾼다.
const MessageContentList = function(room) {
$.ajax({
url:"message_content_list.do",
method:"GET",
data:{
room : room,
},
success:function(data){
console.log("메세지 내용 가져오기 성공");
// 메세지 내용을 html에 넣는다
$('.msg_history').html(data);
// 이 함수로 메세지 내용을 가져올때마다 스크롤를 맨아래로 가게 한다.
$(".msg_history").scrollTop($(".msg_history")[0].scrollHeight);
},
error : function() {
alert('서버 에러');
}
})
$('.unread'+room).empty();
};
메세지 리스트를 가져오는 함수에서 아래와 같이 호출된다.
// 메세지 내용을 불러오는 함수 호출
MessageContentList(room);
2) message_ajax_list.jsp
> view > message > message_ajax_list.jsp
message_list.jsp에서 ajax 처리로 불러오는 메세지 리스트 jsp 코드이다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:forEach var="tmp" items="${list }">
<div class="chat_list_box${tmp.room } chat_list_box">
<div type="button" class="chat_list" room="${tmp.room }" other-nick="${tmp.other_nick }">
<!-- active-chat -->
<div class="chat_people">
<div class="chat_img" >
<a href="other_profile.do?other_nick=${tmp.other_nick }">
<img src="./upload/profile/${tmp.profile}" alt="sunil" >
</a>
</div>
<div class="chat_ib">
<h5>${tmp.other_nick }<span class="chat_date">${tmp.send_time }</span>
</h5>
<div class="row">
<div class="col-10">
<p>${tmp.content }</p>
</div>
<%-- 만약 현재사용자가 안읽은 메세지 갯수가 0보다 클때만 badge를 표시한다. --%>
<c:if test="${tmp.unread > 0 }">
<div class="col-2 unread${tmp.room }">
<span class="badge bg-danger">${tmp.unread }</span>
</div>
</c:if>
</div>
</div>
</div>
</div>
</div>
</c:forEach>
3) message_content_list.jsp
> view > message > message_content_list.jsp
message_list.jsp에서 ajax로 불러오는 메세지 내용 jsp 코드이다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:forEach var="tmp" items="${clist }">
<c:choose>
<c:when test="${sessionScope.nick ne tmp.send_nick }">
<!-- 받은 메세지 -->
<div class="incoming_msg">
<div class="incoming_msg_img">
<a href="other_profile.do?other_nick=${tmp.send_nick }">
<img src="./upload/profile/${tmp.profile }" alt="보낸사람 프로필">
</a>
</div>
<div class="received_msg">
<div class="received_withd_msg">
<p>${tmp.content }</p>
<span class="time_date"> ${tmp.send_time }</span>
</div>
</div>
</div>
</c:when>
<c:otherwise>
<!-- 보낸 메세지 -->
<div class="outgoing_msg">
<div class="sent_msg">
<p>${tmp.content }</p>
<span class="time_date"> ${tmp.send_time }</span>
</div>
</div>
</c:otherwise>
</c:choose>
</c:forEach>
3-2. Controller
> com.exam.controller > MessageController.java
package com.exam.controller;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.exam.model1.message.MessageDAO;
import com.exam.model1.message.MessageTO;
/**
* Handles requests for the application home page.
*/
@Controller
public class MessageController {
@Autowired
private MessageDAO messageDao;
// 메세지 목록
@RequestMapping(value = "/message_list.do")
public String message_list(HttpServletRequest request, HttpSession session) {
// System.out.println("현대 사용자 nick : " + session.getAttribute("nick"));
String nick = (String) session.getAttribute("nick");
MessageTO to = new MessageTO();
to.setNick(nick);
// 메세지 리스트
ArrayList<MessageTO> list = messageDao.messageList(to);
request.setAttribute("list", list);
return "message/message_list";
}
// 메세지 목록
@RequestMapping(value = "/message_ajax_list.do")
public String message_ajax_list(HttpServletRequest request, HttpSession session) {
// System.out.println("현대 사용자 nick : " + session.getAttribute("nick"));
String nick = (String) session.getAttribute("nick");
MessageTO to = new MessageTO();
to.setNick(nick);
// 메세지 리스트
ArrayList<MessageTO> list = messageDao.messageList(to);
request.setAttribute("list", list);
return "message/message_ajax_list";
}
@RequestMapping(value = "/message_content_list.do")
public String message_content_list(HttpServletRequest request, HttpSession session) {
int room = Integer.parseInt(request.getParameter("room"));
MessageTO to = new MessageTO();
to.setRoom(room);
to.setNick((String) session.getAttribute("nick"));
// 메세지 내용을 가져온다.
ArrayList<MessageTO> clist = messageDao.roomContentList(to);
request.setAttribute("clist", clist);
return "message/message_content_list";
}
// 메세지 리스트에서 메세지 보내기
@ResponseBody
@RequestMapping(value = "/message_send_inlist.do")
public int message_send_inlist(@RequestParam int room, @RequestParam String other_nick,
@RequestParam String content, HttpSession session) {
MessageTO to = new MessageTO();
to.setRoom(room);
to.setSend_nick((String) session.getAttribute("nick"));
to.setRecv_nick(other_nick);
to.setContent(content);
int flag = messageDao.messageSendInlist(to);
return flag;
}
}
여러 request에 대한 mapping이 되어 있다.
3-3. DAO
> com.exam.model1.message > messaageDAO.java
package com.exam.model1.message;
import java.util.ArrayList;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class MessageDAO {
@Autowired
private SqlSession sqlSession;
// 메세지 리스트
public ArrayList<MessageTO> messageList(MessageTO to) {
String nick = to.getNick();
// 메세지 리스트에 나타낼 것들 가져오기 - 가장 최근 메세지, 보낸사람 profile 사진, 보낸사람 nick
ArrayList<MessageTO> list = (ArrayList) sqlSession.selectList("message_list", to);
for (MessageTO mto : list) {
mto.setNick(nick);
// 현재 사용자가 해당 room에서 안읽은 메세지의 갯수를 가져온다.
int unread = sqlSession.selectOne("count_unread", mto);
// 현재 사용자가 메세지를 주고받는 상대 profile을 가져온다.
String profile = sqlSession.selectOne("get_other_profile",mto);
// 안읽은 메세지 갯수를 mto에 set한다.
mto.setUnread(unread);
// 메세지 상대의 프로필사진을 mto에 set한다.
mto.setProfile(profile);
// 메세지 상대 nick을 세팅한다. other_nick
if (nick.equals(mto.getSend_nick())) {
mto.setOther_nick(mto.getRecv_nick());
} else {
mto.setOther_nick(mto.getSend_nick());
}
}
return list;
}
// room 별 메세지 내용을 가져온다.
public ArrayList<MessageTO> roomContentList(MessageTO to) {
System.out.println("room : " + to.getRoom());
System.out.println("recv_nick : " + to.getRecv_nick());
System.out.println("nick : " + to.getNick());
// 메세지 내역을 가져온다
ArrayList<MessageTO> clist = (ArrayList) sqlSession.selectList("room_content_list", to);
// 해당 방의 메세지들 중 받는 사람이 현재사용자의 nick인 메세지를 모두 읽음 처리한다
sqlSession.update("message_read_chk", to);
return clist;
}
// 메세지 list에서 메세지를 보낸다.
public int messageSendInlist(MessageTO to) {
// 메세지리스트에서 보낸건지 프로필에서 보낸건지 구분하기 위함
if(to.getRoom() == 0) { // room이 0이라면 프로필에서 보낸거다
int exist_chat = sqlSession.selectOne("exist_chat", to);
// 프로필에서 보낸것중 메세지 내역이없어서 첫메세지가 될경우를 구분하기 위함
if(exist_chat == 0) { // 메세지 내역이 없어서 0이면 message 테이블의 room 최댓값을 구해서 to에 set 한다.
int max_room = sqlSession.selectOne("max_room", to);
to.setRoom(max_room+1);
}else { // 메세지 내역이 있다면 해당 room 번호를 가져온다.
int room = Integer.parseInt(sqlSession.selectOne("select_room", to) );
to.setRoom(room);
}
}
int flag = sqlSession.insert("messageSendInlist",to);
return flag;
}
}
3-4. TO
> com.exam.model1.message > messaageTO.java
package com.exam.model1.message;
public class MessageTO {
private String no;
private int room;
private String send_nick;
private String recv_nick;
private String send_time;
private String read_time;
private String content;
private String read_chk;
// 현재 사용자의 메세지 상대 nick을 담는다.
private String other_nick;
// 현재 사용자의 메세지 상대 profile을 담는다.
private String profile;
// 현재 사용자 nick
private String nick;
// 안읽은 메세지 갯수
private int unread;
public int getUnread() {
return unread;
}
public void setUnread(int unread) {
this.unread = unread;
}
public String getOther_nick() {
return other_nick;
}
public void setOther_nick(String other_nick) {
this.other_nick = other_nick;
}
public String getProfile() {
return profile;
}
public void setProfile(String profile) {
this.profile = profile;
}
public int getRoom() {
return room;
}
public void setRoom(int room) {
this.room = room;
}
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getSend_nick() {
return send_nick;
}
public void setSend_nick(String send_nick) {
this.send_nick = send_nick;
}
public String getRecv_nick() {
return recv_nick;
}
public void setRecv_nick(String recv_nick) {
this.recv_nick = recv_nick;
}
public String getSend_time() {
return send_time;
}
public void setSend_time(String send_time) {
this.send_time = send_time;
}
public String getRead_time() {
return read_time;
}
public void setRead_time(String read_time) {
this.read_time = read_time;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getRead_chk() {
return read_chk;
}
public void setRead_chk(String read_chk) {
this.read_chk = read_chk;
}
}
3-5. SQL(mapper)
<!-- ========================= 메세지 ======================= -->
<!-- 메세지 리스트 가져오기 -->
<select id="message_list" parameterType="com.exam.model1.message.MessageTO" resultType="com.exam.model1.message.MessageTO">
select no, room, send_nick, recv_nick, date_format(send_time, '%Y-%m-%d %H:%i') send_time, read_time, content, read_chk
from message
where no in (select max(no) from message group by room) and (send_nick = #{nick} or recv_nick=#{nick})
order by no desc;
</select>
<!-- 메세지 list에서 상대방 profile 가져오기 -->
<select id="get_other_profile" parameterType="com.exam.model1.message.MessageTO" resultType="String">
select profile from user
<choose>
<when test="send_nick == nick">
where nick = #{recv_nick}
</when>
<otherwise>
where nick = #{send_nick}
</otherwise>
</choose>
</select>
<!-- 안읽은 메세지 갯수 가져오기 -->
<select id="count_unread" parameterType="com.exam.model1.message.MessageTO" resultType="Int">
select count(no) from message
where recv_nick=#{nick} and read_chk=0 and room=#{room}
</select>
<!-- 메세지 내용 가져오기 -->
<select id="room_content_list" parameterType="com.exam.model1.message.MessageTO" resultType="com.exam.model1.message.MessageTO">
select m.no, m.room, m.send_nick, m.recv_nick, date_format(m.send_time, '%Y-%m-%d %H:%i') send_time, m.read_time, m.content, m.read_chk, u.profile
from message m left outer join user u
on m.send_nick = u.nick
<choose>
<when test="room != 0">
where room=#{room}
</when>
<otherwise>
where (recv_nick = #{recv_nick} and send_nick = #{nick}) or (send_nick = #{recv_nick} and recv_nick = #{nick})
</otherwise>
</choose>
</select>
<!-- 메세지 읽음 처리 -->
<update id="message_read_chk" parameterType="com.exam.model1.message.MessageTO">
update message set read_chk=1
<choose>
<when test="room != 0">
where room=#{room} and read_chk=0 and recv_nick=#{nick}
</when>
<otherwise>
where send_nick=#{recv_nick} and read_chk=0 and recv_nick=#{nick}
</otherwise>
</choose>
</update>
<!-- 메세지리스트에서 메세지 보내기 -->
<insert id="messageSendInlist" parameterType="com.exam.model1.message.MessageTO">
<choose>
<when test="room != 0">
insert into message values(0, #{room}, #{send_nick}, #{recv_nick}, now(), now(), #{content}, 0);
</when>
<otherwise>
insert into message values(0, #{room}, #{send_nick}, #{recv_nick}, now(), now(), #{content}, 0);
</otherwise>
</choose>
</insert>
<!-- room 번호 최댓값 구하기 -->
<select id="max_room" parameterType="com.exam.model1.message.MessageTO" resultType="Int">
select max(room) from message
</select>
<!-- 메세지 이력이 있는지 검색 -->
<select id="exist_chat" parameterType="com.exam.model1.message.MessageTO" resultType="Int">
select count(no) from message
where (recv_nick = #{recv_nick} and send_nick=#{send_nick}) or (send_nick = #{recv_nick} and recv_nick=#{send_nick})
</select>
<!-- 기존 메세지 내역의 room 번호를 가져옴 -->
<select id="select_room" parameterType="com.exam.model1.message.MessageTO" resultType="String">
select room from message
where (recv_nick = #{recv_nick} and send_nick=#{send_nick}) or (send_nick = #{recv_nick} and recv_nick=#{send_nick})
limit 0,1
</select>
※ CSS
> webapp > resources > css > message_list.css
@charset "UTF-8";
img{
/*글쓴이의 프로필 사진을 둥글게*/
width: 40px;
height: 40px;
border: 0px;
/*border: 1px solid #cecece;*/
border-radius: 50%;
}
p {
font-family: 'Noto Sans KR', sans-serif;
font-size: 20px;
}
.badge{
margin-left: 15px;
}
.msg-container{max-width:1170px; margin:auto;}
img{ max-width:100%;}
.inbox_people {
background: #f8f8f8 none repeat scroll 0 0;
float: left;
overflow: hidden;
width: 40%; border-right:1px solid #f7f7f7;
}
.inbox_msg {
border: 1px solid #f7f7f7;
border-radius: 15px;
clear: both;
overflow: hidden;
}
.top_spac{ margin: 20px 0 0;}
.recent_heading {float: left; width:40%;}
.srch_bar {
display: inline-block;
text-align: right;
width: 60%; padding:
}
.headind_srch{ padding:10px 29px 10px 20px; overflow:hidden; border-bottom:1px solid #f7f7f7;}
.recent_heading h4 {
color: #5fcf80;
font-size: 30px;
margin: auto;
font-family: 'Nanum Pen Script', cursive;
}
.srch_bar input{ border:1px solid #cdcdcd; border-width:0 0 1px 0; width:80%; padding:2px 0 4px 6px; background:none; font-family: 'Nanum Pen Script', cursive; font-size:25px;}
.srch_bar .input-group-addon button {
background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
border: medium none;
padding: 0;
color: #707070;
font-size: 18px;
}
.srch_bar .input-group-addon { margin: 0 0 0 -27px;}
.chat_ib h5{ font-size:20px; color:#464646; margin:0 0 8px 0; font-family: 'Nanum Pen Script', cursive;}
.chat_ib h5 span{ font-size:17px; float:right;}
.chat_ib p{ font-size:14px; color:#989898; margin:auto}
.chat_img {
float: left;
width: 11%;
}
.chat_ib {
float: left;
padding: 0 0 0 15px;
width: 88%;
}
.chat_people{ overflow:hidden; clear:both;}
.chat_list {
border-bottom: 1px solid #f7f7f7;
margin: 0;
padding: 18px 16px 10px;
}
.chat_list_box :hover{
background-color: #d6ead0;
}
.inbox_chat { height: 550px; overflow-y: scroll;}
.active_chat{ background:#ebebeb;}
.incoming_msg_img {
display: inline-block;
width: 6%;
}
.received_msg {
display: inline-block;
padding: 0 0 0 10px;
vertical-align: top;
width: 92%;
}
.received_withd_msg p {
background: #f4f4f4 none repeat scroll 0 0;
border-radius: 7px;
color: #646464;
font-size: 14px;
margin: 0;
padding: 10px 10px 10px 12px;
width: 100%;
font-family: 'Noto Sans KR', sans-serif;
}
.time_date {
color: #747474;
display: block;
font-size: 12px;
margin: 5px 0 8px;
}
.received_withd_msg { width: 57%;}
.mesgs {
float: left;
padding: 30px 15px 0 25px;
width: 60%;
}
.sent_msg p {
background: #97df93 none repeat scroll 0 0;
border-radius: 7px;
font-size: 14px;
margin: 0; color:#fff;
padding: 10px 10px 10px 12px;
width:100%;
font-family: 'Noto Sans KR', sans-serif;
}
.outgoing_msg{ overflow:hidden; margin:26px 0 26px;}
.sent_msg {
float: right;
width: 46%;
font-family: 'Noto Sans KR', sans-serif;
}
.input_msg_write input {
background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
border: medium none;
color: #4c4c4c;
font-size: 15px;
min-height: 48px;
width: 100%;
}
.type_msg {border-top: 1px solid #dfdfdf;position: relative;}
.msg_send_btn {
background: #97df93 none repeat scroll 0 0;
border: medium none;
border-radius: 50%;
color: #fff;
cursor: pointer;
font-size: 17px;
height: 33px;
position: absolute;
right: 0;
top: 11px;
width: 33px;
}
.msg_send_btn:hover{
background: #5fcd58 none repeat scroll 0 0;
}
.messaging { padding: 0 0 50px 0;}
.msg_history {
height: 516px;
overflow-y: auto;
}
'빅데이터 플랫폼 구축을 위한 자바 개발자 양성과정 > 랜선여행 커뮤니티 프로젝트' 카테고리의 다른 글
Spring MVC 에 소셜로그인(카카오로그인) 구현하기 - JavaScript 키 (18) | 2021.04.27 |
---|---|
Spring MVC 로 무한 스크롤, 검색 구현하기 (8) | 2021.04.22 |
Spring MVC 로 댓글(답글) 구현하기 (16) | 2021.04.21 |
Spring MVC 로 하트(좋아요) 구현하기 - 모달창 포함 (10) | 2021.04.21 |
Web socket을 활용한 실시간 댓글 알람 기능 구현 (0) | 2021.03.30 |