학원/spring

1.25 (tiles-그룹채팅 멤버 초대, 채팅방 생성)

쿠룽지 2024. 1. 25. 22:24
728x90
반응형

 

 

 

 

<채팅 초대 멤버 선택 해제>

 

 

 

 

message.talk.js

//선택한 채팅방 멤버 삭제
$(document).on('click','.member-span',function(){
    let id = $(this).attr('data-id');
    //채팅 멤버가 저장된 배열에서 삭제할 멤버의 id를 제거
    member_list.splice(member_list.indexOf(id),1);
    $(this).remove(); // this=이벤트가 발생한 span태그

    if($('#name_checked').is(':checked')){//채팅방 이름 자동생성이 설정되어있다면
        makeRoom_name();
    }

    if($('#talk_member span').length == 0){ //개설자밖에 없을 경우
        //초기화
        $('#name_span').text(''); //span태그(보여짐)
        $('#basic_name').val('');//input태그(내부적으로 동작)
    }
});

member_list.splice(member_list.indexOf(id),1);
id가 있는 index에서 1개만 지우겠다 라는 뜻

실행 후 채팅방 회원 다 x자 눌러서
삭제하면 채팅방 이름이 초기화됨

 

 

 

 

 

 

이전에 만들었던 자바빈 파일에 넣고 작업 다시 시작

kr.spring.talk.vo

TalkMemberVO

package kr.spring.talk.vo;

import java.sql.Date;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class TalkMemberVO {
	private int talkroom_num;
	private int mem_num;
	private String room_name;
	private Date member_date;
	
	//추가
	private String id;
}

 

 

 

 

 

 

SQL문 작성

TalkMapper.java

//채팅방 번호 생성 (PK)
@Select("SELECT sptalkroom_seq.nextval FROM dual")
public int selectTalkRoomNum();
//채팅방 생성
@Insert("INSERT INTO sptalkroom (talkroom_num,basic_name) VALUES (#{talkroom_num},#{basic_name})")
public void insertTalkRoom(TalkRoomVO talkRoomVO);
//채팅방 멤버 등록
@Insert("INSERT INTO sptalk_member (talkroom_num,room_name,mem_num) VALUES (#{talkroom_num},#{room_name},#{mem_num})")
public void insertTalkRoomMember(@Param(value="talkroom_num") int talkroom_num,
                                 @Param(value="room_name") String room_name,
                                 @Param(value="mem_num") int mem_num);

talkroom / talkroommember table에 insert하는 sql문 작성

 

 

 

 

 

 

서비스 파일

TalkServiceImpl

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;

@Service
@Transactional
public class TalkServiceImpl implements TalkService{
	
	@Autowired
	private TalkMapper talkMapper;
	
	@Override
	public List<TalkRoomVO> selectTalkRoomList(Map<String, Object> map) {
		return null;
	}

	@Override
	public int selectRowCount(Map<String, Object> map) {
		return 0;
	}

	@Override
	public void insertTalkRoom(TalkRoomVO talkRoomVO) {
		//기본키 생성해서 넣어줌
		talkRoomVO.setTalkroom_num(talkMapper.selectTalkRoomNum());
		//채팅방 생성
		talkMapper.insertTalkRoom(talkRoomVO);
		
		//입장 메시지 처리
		
		//채팅방 멤버 생성
		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 null;
	}
}

TalkServiceImpl 안에

 

insertTalkRoom >> selectTalkRoomNum + insertTalkRoom + insertTalkRoomMember (TalkMapper 안 메서드)

 

 

 

 

 

 

 

TalkVO 작성

kr.spring.talk.vo

TalkVO

package kr.spring.talk.vo;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class TalkVO {
	private int talk_num;
	private int talkroom_num; //수신그룹
	private int mem_num; //발신자
	private String message;
	private String chat_date;
	
	//추가
	private int read_count; //읽지않은 메시지 수
	private String id;
}

 

 

 

 

 

 

컨트롤러 수정

TalkController

/* ============================
 * 채팅방 생성
 * ============================*/
//채팅방 생성폼 호출
@GetMapping("/talk/talkRoomWrite")
public String talkRoomWrite() {
    return "talkRoomWrite"; //tiles설정
}

//전송된 데이터 처리
@PostMapping("/talk/talkRoomWrite")
public String talkRoomSubmit(TalkRoomVO vo, HttpSession session) {
    log.debug("<<채팅방 생성 TalkRoomVO>> : " + vo);

    MemberVO user = (MemberVO)session.getAttribute("user");

    //채팅멤버 초대 시 문구설정
    vo.setTalkVO(new TalkVO());
    vo.getTalkVO().setTalkroom_num(vo.getTalkroom_num());
    vo.getTalkVO().setMem_num(user.getMem_num()); //session에서 가져온 멤버 정보 넣기
    vo.getTalkVO().setMessage(user.getId()+"님이 "
                       +findMemberId(vo,user)+"님을 초대했습니다.@{member}@");
    talkService.insertTalkRoom(vo);

    return "redirect:/talk/talkList";
}


/* ============================
 * 초대한 회원의 id구하기
 * ============================*/	
//내부적으로만 호출되기 때문에 private으로 호출
private String findMemberId(TalkRoomVO vo, MemberVO user) {
    String member_id = "";
    int[] members = vo.getMembers();
    for(int i=0;i<members.length;i++) {
        String temp_id = memberService.selectMember(members[i]).getId();
        //초대한 사람의 아이디는 제외
        if(!user.getId().equals(temp_id)) {
            member_id += temp_id;
            if(i < members.length-1) member_id += ", ";
        }
    }
    return member_id;
}

1.
vo.getTalkVO().setMessage(user.getId()+"님이 "+findMemberId(vo,user)+"님을 초대했습니다.@{member}@");
findMemberId(vo,user) == 멤버 아이디를 알려주는 메서드
@{member}@ << 안내메시지를 알려주는 특별한 기호

2.
private String findMemberId(TalkRoomVO vo, MemberVO user) {
MemberVO user 가 위 session 정보를 받은 user (로그인한 개설자) 임

3.
if(i < members.length-1) member_id += ", ";
마지막 사람 전까지는 , 넣음
예) 길동, 문래 님 << 이런식으로

 

 

 

 

 

 

 

채팅방 생성 후 전송 시 조건체크하는 구문 추가

message.talk.js

//채팅방 생성 전송
$('#talk_form').submit(function(){
    if(member_list.length<=1){
        //이미 배열에 로그인한 유저(채팅방 개설자)가 기본 등록되어 있어서
        //로그인한 유저 포함 최소 2명이 되어야 채팅 가능
        alert('채팅에 참여할 회원을 검색하세요');
        $('#member_search').focus();
        return false;
    }
});

member_list에 본인만 있다면 alert창 표시

 

============================

아직 목록작업이 안되어 있기 때문에 채팅방 생성 후 oracle에서 데이터 확인 가능

sptalkroom / sptalk_member 순으로 테이블 확인

sptalkroom은 생성된 방 1컬럼만,
sptalk_member엔 각자 채팅방 이름 변경 가능하게끔 인원수만큼 컬럼 생성됨

 

 

 

 

 


 

 

 

 

 

<채팅방 목록처리>

 

 

 

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>
	
	<!-- 개수 -->
	<select id="selectRowCount" parameterType="map" resultType="integer">
		SELECT
		  COUNT(*)
		FROM sptalkroom
	</select>
	
	<!-- 목록 -->
	<select id="selectTalkRoomList" parameterType="map" resultMap="talkMap">
		SELECT
		  *
		FROM (SELECT
				a.*,
				rownum rnum
			  FROM (SELECT
			  		  *
			  		FROM sptalkroom
			  		ORDER BY talkroom_num DESC)a)		
		<![CDATA[
		WHERE rnum >= #{start} AND rnum <= #{end}
		]]>
	</select>
</mapper>

1.
<resultMap type="talkRoomVO" id="talkMap">
type=자바빈이름 id=설정id (자기마음대로 지어도 됨)


TalkRoomVO에 
private TalkVO talkVO;
private TalkMemberVO talkMemberVO; 를 이미 넣음

얘네는 인자가 하나가 아니기 때문에 수동으로 인자를 걸어야 매핑이 됨
한 컬럼이 아닌 다른 테이블 전체 정보를 읽어오기 위해선 이렇게 resultMap(?)으로 조인해야한다고 함

2.
<result property="talkVO.message" column="message"/>
property=자바빈.컬럼 column=컬럼

talkVO 안에 있는 message, chat_date / talkMemberVO 안에 있는 room_name


3.
<select id="selectTalkRoomList" parameterType="map" resultMap="talkMap">
resultMap  有 resultMap
resultMap  無 resultType

 

우선은 조인하지않고 화면 출력
확인 후 조인연결

 

 

 

 

 

ServiceImpl 파일 

TalkServiceImpl

@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);
}

 

 

 

 

 

 

 

컨트롤러 목록 구문 추가

TalkController

/* ============================
 * 채팅방 목록
 * ============================*/
@RequestMapping("/talk/talkList")
public String chatList(@RequestParam(value="pageNum",defaultValue="1") int currentPage,
                       String keyword, HttpSession session, Model model) {

    MemberVO user = (MemberVO)session.getAttribute("user");

    Map<String,Object> map = new HashMap<String,Object>();
    map.put("keyword", keyword);
    map.put("mem_num", user.getMem_num()); //사용자 본인 채팅목록만 빼내기 위해

    int count = talkService.selectRowCount(map);

    //keyfield가 없기 때문에 그냥 null처리하면 됨 (30개10페이지)
    PageUtil page = new PageUtil(null,keyword,currentPage,count,30,10,"talkList");

    List<TalkRoomVO> list = null;
    if(count>0) {
        map.put("start", page.getStartRow());
        map.put("end", page.getEndRow());
        list = talkService.selectTalkRoomList(map);
    }
    model.addAttribute("count", count);
    model.addAttribute("list", list);
    model.addAttribute("page", page.getPage());

    return "talkList";
}

 

 

 

 

 

 

 

 

 

출력 화면 

views

talk

talkList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!-- 내용 시작 -->
<div class="page-main">
	<h2>채팅리스트</h2>
	<!-- 검색 시작 -->
	<form action="talkList" id="search_form" method="get">
		<ul class="search">
			<li>
				<input type="search" name="keyword" id="keyword" value="${param.keyword}">
			</li>
			<li>
				<input type="submit" value="찾기">
				<input type="button" value="목록" onclick="location.href='talkList'">
			</li>
		</ul>
	</form>
	<!-- 검색 끝 -->
	<div class="align-right">
		<input type="button" value="채팅방 생성" onclick="location.href='talkRoomWrite'">
	</div>
	<c:if test="${count == 0}">
	<div class="result-display">표시할 채팅방이 없습니다</div>
	</c:if>
	<c:if test="${count > 0}">
	<table class="striped-table">
		<!-- 따로 구분하는 항목이 없고 나열만 할거라 그냥 반복 -->
		<c:forEach var="talk" items="${list}">
		<tr>
			<td style="text-align:left;">
				<a href="talkDetail?talkroom_num=${talk.talkroom_num}">
					<b>${talk.talkMemberVO.room_name}(${talk.room_cnt})</b>
					<br>
					<span>${fn:substring(talk.talkVO.message,0,45)}</span>
				</a>
			</td>
			<td>
				<c:if test="${!empty talk.talkVO.chat_date}">${talk.talkVO.chat_date}</c:if>
				<c:if test="${empty talk.talkVO.chat_date}">${talk.talkroom_date}</c:if>
			</td>
		</tr>
		</c:forEach>
	</table>
	<div class="align-center">${page}</div>
	</c:if>
</div>
<!-- 내용 끝 -->

방이름(읽지않은 메시지 수)

제일 최근 메시지 45자 이내로 표시

 

1.
<b>${talk.talkMemberVO.room_name}(${talk.room_cnt})</b>
talkRoomVO에서 talkMemberVO를 넣었기 때문에 저렇게 불러올 수 있음

2.
<span>${fn:substring(talk.talkVO.message,0,45)}</span>
functions lib를 사용해서 메시지가 길면 잘라서 보여줌

3.
<c:if test="${empty talk.talkVO.chat_date}">${talk.talkroom_date}</c:if>
채팅한 날짜가 있으면 채팅날짜
없으면 채팅방 개설날짜 보여줌

============================

로그인 후 mypage > 채팅
들어가면

(0)     2024-01-25 10:39:35

이렇게 채팅방 뜸

 

 

 

 


 

 

 

 

 

 

지금까지 넣었던 데이터 모두 지우고 채팅방 생성+문구 저장이 잘 됐는지 확인해보기

(오라클 sptalk_member/ sptalkroom)

 

 

 

 

초대 문구 처리

 

 

 

메서드+SQL문 작성

TalkMapper.java

//채팅 메시지 번호 생성
@Select("SELECT sptalk_seq.nextval FROM dual")
public int selectTalkNum();
//채팅 메시지 등록
@Insert("INSERT INTO sptalk (talk_num,talkroom_num,mem_num,message) VALUES (#{talk_num},#{talkroom_num},#{mem_num},#{message})")
public void insertTalk(TalkVO talkVO);
//읽지 않은 채팅 기록 저장
public void insertTalkRead(@Param(value="talkroom_num") int talkroom_num,
                           @Param(value="talk_num") int talk_num,
                           @Param(value="mem_num") int mem_num);
//채팅 메시지 읽기
public List<TalkVO> selectTalkDetail(Map<String,Integer> map);
//읽은 채팅 기록 삭제
public void deleteTalkRead(Map<String,Integer> map);

 

 

 

 

 

 

 

서비스 파일에 코드 추가

TalkServiceImpl

@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);
    }
}

채팅방pk 생성

채팅방 생성

 

채팅메시지pk 생성

위에서 생성한 채팅방pk talkRoomVO에 넣음

채팅메시지 등록

 

채팅방멤버 등록

 

============================

talkcontroller의 채팅방생성-초대시 문구설정 이거랑 연계해서 같이 작업하는거임

serviceimpl
talkMapper.insertTalk(talkRoomVO.getTalkVO());
이게

talkmapper.java
//채팅 메시지 등록
@Insert("INSERT INTO sptalk (talk_num,talkroom_num,mem_num,message) VALUES (#{talk_num},#{talkroom_num},#{mem_num},#{message})")
public void insertTalk(TalkVO talkVO);
이거임

============================

restart 후

[화면출력]
아직 join을 안했기 때문에 이전과 동일

[oracle]
sptalkroom > 1컬럼 생성
sptalk_member > 인원수만큼 컬럼 생성
sptalk > talkroom_num, mem_num(생성자), message (a 님이 b,c님을 초대했습니다.)

저장됨

 

 

 

 

 

 

sql문장 조인으로 좀더 자세히 작성

TalkMapper.xml

<!-- 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,'<','&lt;'),'>','&gt;'),'@{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>

sql태그 > 채팅방 목록을 보여주기 위한 sub_sql문

1.
REPLACE(REPLACE(REPLACE(message,'<','&lt;'),'>','&gt;'),'@{member}@','') message,
기존과 같은 방식으로 replace처리할 때 아까 처음에 초대 문구 작성했을 때 넣었던 @{member}@을 안 보이게 처리

2.
FROM sptalk WHERE talk_num IN (SELECT
sptalk안에서도 제일 최신 메시지 1건만 보여주기 위해 조건체크 수행
MAX(talk_num) talk_num << 이게 제일 최근 메시지임 (max)

3.
sptalk_member에 있는 mem_num과 조인하고 싶은거라 m 알리아스를 사용해서
WHERE m.mem_num=#{mem_num}
라고 지정함

 

 

 

728x90
반응형