김미썸코딩

Spring MVC 로 메세지 기능 구현 본문

728x90

다른 사람 프로필 사진을 누르면 그 사람의 프로필 페이지로 이동이된다. 

다른 사람 프로필 페이지에선 최초로 쪽지를 보낼수 있고, 쪽지함에서 쪽지를 보낼수도 있다.

 

다만, 새로운 메세지가 왔을 때 실시간으로 바로 반영이 되지 않고, 새로고침이 실행될때 반영이 되기때문에

몇초마다 페이지 전체 혹은 일부가 리로드 되는 코드를 추가해야한다.

 

 


*** 순서 ***

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

  1. message_list.jsp : 메세지함 페이지 html로 메인 html
  2. message_ajax_list.jsp : 메세지함의 메세지 리스트부분 html (메세지함 페이지에 동적으로 삽입됨)
  3. 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;
}
728x90
Comments