모든 작성은 끝
이제 채팅 연결
<목록 표시하기>
TalkMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.spring.talk.dao.TalkMapper">
<!-- 사용할 map설정 -->
<resultMap type="talkRoomVO" id="talkMap">
<result property="talkVO.message" column="message"/>
<result property="talkVO.chat_date" column="chat_date"/>
<result property="talkMemberVO.room_name" column="room_name"/>
</resultMap>
<!-- sql태그 -->
<sql id="talkSub">
FROM sptalkroom JOIN sptalk_member m USING(talkroom_num)
LEFT OUTER JOIN (SELECT
talkroom_num,
mem_num,
COUNT(*) room_cnt
FROM sptalk_read
WHERE mem_num=#{mem_num}
GROUP BY talkroom_num,mem_num) USING (talkroom_num)
LEFT OUTER JOIN (SELECT
talk_num,
<![CDATA[
REPLACE(REPLACE(REPLACE(message,'<','<'),'>','>'),'@{member}@','') message,
]]>
chat_date,
talkroom_num
FROM sptalk WHERE talk_num IN (SELECT
MAX(talk_num) talk_num
FROM sptalk
GROUP BY talkroom_num))
USING(talkroom_num)
WHERE m.mem_num=#{mem_num}
<if test="keyword != null and keyword != ''">
AND room_name LIKE '%' || #{keyword} || '%'
</if>
</sql>
<!-- 개수 -->
<select id="selectRowCount" parameterType="map" resultType="integer">
SELECT
COUNT(*)
<include refid="talkSub"></include>
</select>
<!-- 목록 -->
<select id="selectTalkRoomList" parameterType="map" resultMap="talkMap">
SELECT
*
FROM (SELECT
a.*,
rownum rnum
FROM (SELECT
*
<include refid="talkSub"></include>
ORDER BY chat_date DESC)a)
<![CDATA[
WHERE rnum >= #{start} AND rnum <= #{end}
]]>
</select>
</mapper>
1.
개수/목록 sql문 둘다
FROM sptalkroom 없애고 talkSub sql문 include
2.
채팅 메시지 날짜=null일 경우 채팅방 날짜 표시
목록에서 <include refid="talkSub"></include> ORDER BY chat_date DESC)a)
chat_date 라고 수정
===========================
실행 결과
<채팅 데이터 읽어오기>
TalkMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.spring.talk.dao.TalkMapper">
<!-- 사용할 map설정 -->
<resultMap type="talkRoomVO" id="talkMap">
<result property="talkVO.message" column="message"/>
<result property="talkVO.chat_date" column="chat_date"/>
<result property="talkMemberVO.room_name" column="room_name"/>
</resultMap>
<!-- sql태그 -->
<sql id="talkSub">
FROM sptalkroom JOIN sptalk_member m USING(talkroom_num)
LEFT OUTER JOIN (SELECT
talkroom_num,
mem_num,
COUNT(*) room_cnt
FROM sptalk_read
WHERE mem_num=#{mem_num}
GROUP BY talkroom_num,mem_num) USING (talkroom_num)
LEFT OUTER JOIN (SELECT
talk_num,
<![CDATA[
REPLACE(REPLACE(REPLACE(message,'<','<'),'>','>'),'@{member}@','') message,
]]>
chat_date,
talkroom_num
FROM sptalk WHERE talk_num IN (SELECT
MAX(talk_num) talk_num
FROM sptalk
GROUP BY talkroom_num))
USING(talkroom_num)
WHERE m.mem_num=#{mem_num}
<if test="keyword != null and keyword != ''">
AND room_name LIKE '%' || #{keyword} || '%'
</if>
</sql>
<!-- 개수 -->
<select id="selectRowCount" parameterType="map" resultType="integer">
SELECT
COUNT(*)
<include refid="talkSub"></include>
</select>
<!-- 목록 -->
<select id="selectTalkRoomList" parameterType="map" resultMap="talkMap">
SELECT
*
FROM (SELECT
a.*,
rownum rnum
FROM (SELECT
*
<include refid="talkSub"></include>
ORDER BY chat_date DESC)a)
<![CDATA[
WHERE rnum >= #{start} AND rnum <= #{end}
]]>
</select>
<!-- 채팅 멤버 읽기 -->
<select id="selectTalkMember" parameterType="integer" resultType="talkMemberVO">
SELECT
mem_num,
id,
room_name
FROM sptalk_member JOIN spmember
USING(mem_num)
WHERE talkroom_num=#{talkroom_num}
</select>
<!-- 채팅 메시지 읽기 -->
<select id="selectTalkDetail" parameterType="integer" resultType="talkVO">
SELECT
<![CDATA[
REPLACE(REPLACE(message,'<','<'),'>','>') message,
]]>
chat_date,
read_count,
mem_num,
id
FROM sptalk
LEFT OUTER JOIN (SELECT
talk_num,
COUNT(*) read_count
FROM sptalk_read
GROUP BY talk_num) USING(talk_num)
JOIN spmember USING(mem_num)
WHERE talkroom_num=#{talkroom_num}
AND chat_date >= (SELECT
member_date
FROM sptalk_member
WHERE talkroom_num=#{talkroom_num}
AND mem_num=#{mem_num}) /*멤버 등록일 이후의 정보만 읽어옴*/
ORDER BY chat_date ASC
</select>
</mapper>
1.
SELECT
member_date
FROM sptalk_member
WHERE talkroom_num=#{talkroom_num}
AND mem_num=#{mem_num})
멤버 초대/등록을 했는데 그 멤버의 초대 전 정보까지 읽어올 순 없기 때문에 등록일 이후의 정보만 읽어오게 함
그래서 sptalk_member에 date가 있는것
2.
ORDER BY chat_date ASC
메시지 정렬은 날짜 오름차순으로 정렬
그래서 최신 메시지가 아래, 위로 올리면 예전 메시지
3.
<![CDATA[
REPLACE(REPLACE(message,'<','<'),'>','>') message,
]]>
chat_date,
read_count,
mem_num,
id
+ 메시지 HTML태그 막기위해 *에서 수동으로 읽어올 정보 다시 지정
<읽은 채팅 기록 삭제 코드 작성>
과부하가 발생하는걸 방지하기 위해 읽은건 삭제
TalkMapper.java
//읽은 채팅 기록 삭제
@Delete("DELETE FROM sptalk_read WHERE talkroom_num=#{talkroom_num} AND mem_num=#{mem_num}")
public void deleteTalkRead(Map<String,Integer> map);
ajax로 실시간 채팅을 구현하기 때문에 구현 순서는
목록 -> detail -> 읽기 -> 쓰기 순으로 작성하는 게 좋을 것 같다고 하심
TalkService에 채팅 메서드 추가 작성
TalkService.java
package kr.spring.talk.service;
import java.util.List;
import java.util.Map;
import kr.spring.talk.vo.TalkMemberVO;
import kr.spring.talk.vo.TalkRoomVO;
import kr.spring.talk.vo.TalkVO;
public interface TalkService {
//채팅방 목록
public List<TalkRoomVO> selectTalkRoomList(Map<String,Object> map);
public int selectRowCount(Map<String,Object> map);
//채팅방 생성
public void insertTalkRoom(TalkRoomVO talkRoomVO);
//채팅 멤버 읽기
public List<TalkMemberVO> selectTalkMember(int talkroom_num);
//채팅 메시지 등록
public void insertTalk(TalkVO talkVO);
//채팅 메시지 읽기
public List<TalkVO> selectTalkDetail(Map<String,Integer> map);
}
TalkMapper 채팅메시지번호생성~ 기록삭제 까지 복사해서 Service파일에 복붙
채팅 메시지 등록
insertTalk 안에 selectTalkNum
insertTalkRead도 내부적으로 하는거라 삭제 / deleteTalkRead도 삭제
++
안 쓰는 자원 한번에 지우는 방법
source > organize imports
누르면 자동으로 import 정리해줌
TalkServiceImpl.java
아까 명시한 순대로 insert보다 select를 먼저 작성
package kr.spring.talk.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import kr.spring.talk.dao.TalkMapper;
import kr.spring.talk.vo.TalkMemberVO;
import kr.spring.talk.vo.TalkRoomVO;
import kr.spring.talk.vo.TalkVO;
@Service
@Transactional
public class TalkServiceImpl implements TalkService{
@Autowired
private TalkMapper talkMapper;
@Override
public List<TalkRoomVO> selectTalkRoomList(Map<String, Object> map) {
return talkMapper.selectTalkRoomList(map);
}
@Override
public int selectRowCount(Map<String, Object> map) {
return talkMapper.selectRowCount(map);
}
@Override
public void insertTalkRoom(TalkRoomVO talkRoomVO) {
//기본키 생성해서 넣어줌
talkRoomVO.setTalkroom_num(talkMapper.selectTalkRoomNum());
//채팅방 생성
talkMapper.insertTalkRoom(talkRoomVO);
//입장 메시지 처리
talkRoomVO.getTalkVO().setTalk_num(talkMapper.selectTalkNum()); //message pk생성
talkRoomVO.getTalkVO().setTalkroom_num(talkRoomVO.getTalkroom_num()); //위에서 만들어진거 가져오기
talkMapper.insertTalk(talkRoomVO.getTalkVO());
//채팅방 멤버 생성
for(int mem_num : talkRoomVO.getMembers()) {
talkMapper.insertTalkRoomMember(talkRoomVO.getTalkroom_num(),
talkRoomVO.getBasic_name(),
mem_num);
}
}
@Override
public List<TalkMemberVO> selectTalkMember(int talkroom_num) {
return talkMapper.selectTalkMember(talkroom_num);
}
//==============================채팅 메시지
@Override
public void insertTalk(TalkVO talkVO) {
// TODO Auto-generated method stub
}
@Override
public List<TalkVO> selectTalkDetail(Map<String, Integer> map) {
//읽은 채팅 기록 삭제
talkMapper.deleteTalkRead(map);
return talkMapper.selectTalkDetail(map);
}
}
deleteTalkRead (읽은 채팅 삭제) + selectTalkDetail(map); (list로 반환)
TalkController
/* ============================
* 채팅 메시지 처리
* ============================*/
//채팅 메시지 페이지 호출
@RequestMapping("/talk/talkDetail")
public String talkDetail(@RequestParam int talkroom_num,
Model model, HttpSession session) {
String chatMember = ""; //빈문자열에 붙이기 위해 변수 생성+초기화
String room_name = "";
MemberVO user = (MemberVO)session.getAttribute("user");
List<TalkMemberVO> list = talkService.selectTalkMember(talkroom_num);
for(int i=0; i<list.size(); i++) {
TalkMemberVO vo = list.get(i);
//로그인한 회원의 채팅방 이름 셋팅
if(user.getMem_num() == vo.getMem_num()) {
room_name = vo.getRoom_name();
}
//채팅 멤버 저장
if(i>0) chatMember += ", ";
chatMember += list.get(i).getId();
}
//채팅 멤버 id
model.addAttribute("chatMember", chatMember);
//채팅 멤버 수
model.addAttribute("chatCount", list.size());
//로그인한 회원의 채팅방 이름
model.addAttribute("room_name", room_name);
return "talkDetail";
}
1.
채팅 페이지 호출 시
1) for문에서 채팅방 이름 셋팅+멤버 저장
2) 저장 작업
(채팅 멤버 수=list.size)
2.
실제 메시지는 ajax통신으로 처리할 거기 때문에 talkDetail return함
tiles-def
talk.xml
</definition>
<definition name="talkDetail" extends="myPage">
<put-attribute name="title" value="채팅하기"/>
<put-attribute name="body" value="/WEB-INF/views/talk/talkDetail.jsp"/>
</definition>
views
talk
talkDetail.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 내용 시작 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.6.0.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/message.talk.js"></script>
<div id="talkDetail" class="page-main">
<h1 id="chatroom_title"><span id="chatroom_name">${room_name}</span>
채팅방 <input type="button" value="채팅방이름 변경" id="change_name">
</h1>
<div class="align-right">
<input type="button" value="목록" onclick="location.href='talkList'">
</div>
<p>
채팅 멤버 :
<span id="chat_member">${chatMember}</span><span id="chat_mcount">(${chatCount}명)</span>
</p>
<div id="chatting_message"></div>
<form method="post" id="detail-form">
<input type="hidden" name="talkroom_num" id="talkroom_num" value="${param.talkroom_num}">
<ul>
<li>
<textarea rows="5" cols="40" name="message" id="message"></textarea>
</li>
</ul>
<div id="message_btn">
<input type="submit" value="전송"> <!-- 메시지 전송하는 버튼 (엔터만 쳐도 전송할 수 있음) -->
</div>
</form>
</div>
<!-- 내용 끝 -->
1.
메시지 입력 form에서 hidden값 = 수신그룹
<input type="hidden" name="talkroom_num" id="talkroom_num" value="${param.talkroom_num}">
>> talkroom_num이 수신그룹 의미
실행 화면
채팅방 클릭 후 상세로 들어가면 다음과 같이 뜸
'학원 > spring' 카테고리의 다른 글
1.30~31 (tiles-채팅 수정/ 방이름 변경) (0) | 2024.01.31 |
---|---|
1.29 (tiles-채팅 상세보기 폼 UI 수정) (0) | 2024.01.29 |
1.25 (tiles-그룹채팅 멤버 초대, 채팅방 생성) (0) | 2024.01.25 |
1.24 (tiles-채팅방 생성,멤버 검색 ajax,선택 이벤트) (0) | 2024.01.25 |
1.23 (tiles-댓글 수정,삭제,duration / 채팅 테이블 생성) (0) | 2024.01.23 |