본문 바로가기
학원/spring

1.24 (tiles-채팅방 생성,멤버 검색 ajax,선택 이벤트)

by 쿠룽지 2024. 1. 25.
728x90
반응형

 

 

 

<채팅방 생성>

웹소켓을 사용해서 실시간 채팅을 만들 예정

 

 

 

VO 3개 생성

kr.spring.talk.vo (package)
TalkRoomVO (class)

TalkVO (class)
TalkMemberVO (class)

 

 

 

TalkRoomVO

package kr.spring.talk.vo;

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

@Getter
@Setter
@ToString
public class TalkRoomVO {
	private int talkroom_num;
    private String basic_name;
    private String talkroom_date;
    
    //추가 vo
    private int[] members; //채팅멤버 배열형태로 읽어오기 
    private int mem_num;
    private int room_cnt; //읽지않은 메시지 수
    
    //다른 vo 읽어오기
    private TalkVO talkVO;
    private TalkMemberVO talkMemberVO;
}

 

 

 

 

 

 

 

kr.spring.talk.dao

TalkMapper (interface)

package kr.spring.talk.dao;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import kr.spring.talk.vo.TalkMemberVO;
import kr.spring.talk.vo.TalkRoomVO;

@Mapper
public interface TalkMapper {
	//채팅방 목록
	public List<TalkRoomVO> selectTalkRoomList(Map<String,Object> map);
	public int selectRowCount(Map<String,Object> map);
	//채팅방 번호 생성 (PK)
	public int selectTalkRoomNum();
	//채팅방 생성
	public void insertTalkRoom(TalkRoomVO talkRoomVO);
	//채팅방 멤버 등록
	public void insertTalkRoomMember(@Param(value="talkroom_num") int talkroom_num,
									 @Param(value="room_name") String room_name,
									 @Param(value="mem_num") int mem_num);
	//채팅 멤버 읽기
	public List<TalkMemberVO> selectTalkMember(int talkroom_num);
	
	//채팅 메시지 번호 생성
	//채팅 메시지 등록
	//읽지 않은 채팅 기록 저장
	//채팅 메시지 읽기
	//읽은 채팅 기록 삭제
	
}

1. selectTalkRoomNum()

2. insertTalkRoom(TalkRoomVO talkRoomVO)

3. insertTalkRoomMember(@Param(value="talkroom_num") int talkroom_num, +room_name, mem_num

 

 

1.
위 기재한 것들이 다 한 세트임
처음 실시할 때 다 만들어줘야함

2.
public int selectRowCount(Map<String,Object> map);
채팅방 목록은 페이지처리 안해도 되는데 너무 많으면 페이지 처리를 하는 게 더 좋다함 혹시 모르니까 목록 처리를 하는 count함수도 사용해서 기재

3.
//채팅방 멤버 등록 메서드
원래 인자 개수가 많으면 Map으로 감싸서 보내는게 맞는데 상황에 따라서 여러 파라미터가 필요하다 ->

그럼 이것처럼 @Param(필수)으로 감싸서 넣으면 됨

=>> 채팅방 번호, 방이름, 회원번호는 insert 시 필수

 

 

 

 

 

서비스 생성 후 메서드 복붙해서 넣기

kr.spring.talk.service

TalkService (interface)

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;

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

}

insertTalkRoom 안에 selectTalkRoomNum, insertTalkRoomMember가 있음 // 같이 처리

 

 

 

 

 

 

 

ServiceImpl 파일 생성

kr.spring.talk.service

TalkServiceImpl (class)

package kr.spring.talk.service;

import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import kr.spring.talk.vo.TalkMemberVO;
import kr.spring.talk.vo.TalkRoomVO;

@Service
@Transactional
public class TalkServiceImpl implements TalkService{
	
	@Override
	public List<TalkRoomVO> selectTalkRoomList(Map<String, Object> map) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int selectRowCount(Map<String, Object> map) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void insertTalkRoom(TalkRoomVO talkRoomVO) {
		// TODO Auto-generated method stub
	}

	@Override
	public List<TalkMemberVO> selectTalkMember(int talkroom_num) {
		// TODO Auto-generated method stub
		return null;
	}
}

 

 

 

 

 

 

 

컨트롤러 파일 생성

kr.spring.talk.controller

TalkController

package kr.spring.talk.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import kr.spring.member.service.MemberService;
import kr.spring.talk.service.TalkService;
import lombok.extern.slf4j.Slf4j;

@Controller
@Slf4j
public class TalkController {
	@Autowired
	private TalkService talkService;
	@Autowired
	private MemberService memberService;
	
	/* ============================
	 * 채팅방 목록
	 * ============================*/
	
	/* ============================
	 * 채팅방 생성
	 * ============================*/
	//채팅방 생성폼 호출
	@GetMapping("/talk/talkRoomWrite")
	public String talkRoomWrite() {
		return "talkRoomWrite"; //tiles설정
	}
	
	/* ============================
	 * 채팅 메시지 처리
	 * ============================*/
}

TalkService와 MemberService autowired함

 

 

 

 

 

 

tiles 매핑

tiles-def

talk.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">

<tiles-definitions>
    <definition name="talkList" extends="myPage">
    	<put-attribute name="title" value="채팅리스트"/>
    	<put-attribute name="body" value="/WEB-INF/views/talk/talkList.jsp"/>
    </definition>
    <definition name="talkRoomWrite" extends="myPage">
    	<put-attribute name="title" value="채팅방 생성"/>
    	<put-attribute name="body" value="/WEB-INF/views/talk/talkRoomWrite.jsp"/>
    </definition>
   
</tiles-definitions>

 

 

 

 

 

 

 

설정파일에 talk.xml + 인터셉트 (채팅) 설정

kr.spring.config

AppConfig

//intercept 등록
@Override
public void addInterceptors(InterceptorRegistry registry) {
    //LoginCheckInterceptor 설정
    registry.addInterceptor(loginCheck)
            .addPathPatterns("/member/myPage")
            .addPathPatterns("/board/write")
            .addPathPatterns("/board/update")
            .addPathPatterns("/board/delete")
            .addPathPatterns("/talk/talkRoomWrite")
            .addPathPatterns("/talk/talkList")
            .addPathPatterns("/talk/talkDetail");
}


@Bean
public TilesConfigurer tilesConfigurer() {
    final TilesConfigurer configurer = new TilesConfigurer();
    //tilesdef.xml의 경로와 파일명 지정
    configurer.setDefinitions(new String[] {"/WEB-INF/tiles-def/main.xml",
                                            "/WEB-INF/tiles-def/member.xml",
                                            "/WEB-INF/tiles-def/board.xml",
                                            "/WEB-INF/tiles-def/talk.xml"
                                            });
    configurer.setCheckRefresh(true);
    return configurer;
}

 

 

 

 

 

 

 

페이지를 호출하기 위해 컨트롤러 수정

TalkController

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

    return "talkList";
}

 

 

 

 

 

 

 

 

 

채팅 기본 페이지 생성

views

talk (folder)

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>
	<div class="align-right">
		<input type="button" value="채팅방 생성" onclick="location.href='talkRoomWrite'">
	</div>
</div>
<!-- 내용 끝 -->

 

 

 


 

 

 

 

 

<채팅방 생성 화면>

 

 

 

views

talk (folder)

talkRoomWrite.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="talkWrite" class="page-main">
	<h2>채팅방 생성</h2>
	<form action="talkRoomWrite" method="post" id="talk_form">
		<input type="hidden" name="members" id="user" data-id="${user.id}" value="${user.mem_num}">
		<ul>
			<li>
				<label for="basic_name">채팅방 이름</label>
				<input type="hidden" name="basic_name" id="basic_name">
				<span id="name_span"></span>
				<input type="checkbox" checked id="name_checked">(자동생성)
			</li>
			<li>
				<label>채팅회원검색</label>
				<input type="text" id="member_search" autocomplete="off">
				<ul id="search_area"></ul>
				<div id="talk_member"></div>
			</li>
		</ul>
		<div class="align-center">
			<input type="submit" value="전송">
			<input type="button" value="목록" onclick="location.href='talkList'">
		</div>
	</form>
</div>
<!-- 내용 끝 -->

TalkRoomVO 안 members[] 를 hidden으로 전송

data-id="${user.id}" value="${user.mem_num}" >> user id (보이는 용도) mem_num 보내는 값

 

-회원 선택 후 js파일에서 배열로 멤버 mem_num 저장

-<div id="talkWrite">

전체 div에 id 넣고 페이지 식별자 부여 -> 페이지를 식별하게 함 (mem_num, id 둘다 필요하기 때문에)

 

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

 

restart 후 채팅방 생성 누르면

멤버 검색하는 폼 보임

 

 

 

 

 

layout.css

/* 채팅방 생성
---------------------*/
#talk_member{
	margin-top:15px;
	padding:10px;
}
.member-span{
	background-color:#CCC;
	border-radius:15px;
	padding: 7px;
	margin: 20px;
	cursor:pointer;
	display: inline-block;
	min-width: 60px;
}
.member-span > sup{
	border-radius: 50%;
	display: inline-block;
	width: 25px;
	height: 10px;
	text-align: center;
	padding-bottom: 15px;
	margin-left: 5px;
	background-color: #FFF;
}
ul#search_area{
	padding: 0;
	width:360px;
	margin-left: 110px;
	border-left: 1px solid black;
	border-right: 1px solid black;
	position: absolute;
	background-color: #FFF;
}
ul#search_area li{
	padding: 8px;
	cursor: pointer;
	border-bottom: 1px solid black;
}

 

 

 

 


 

 

 

 

 

<채팅 멤버 검색 ajax 기능 구현>

 

 

 

resources

static

js

message.talk.js

$(function(){
	let message_socket; //웹소켓 식별자
		
	/*--------------------------
	*	채팅 회원 저장
	* --------------------------*/
	let member_list = []; //채팅 회원을 저장하는 배열
	//채팅방 멤버를 저장하는 배열
	//채팅방 또는 채팅 페이지를 인식해서 채팅방 멤버를 초기 셋팅함
	if($('#talkWrite').length>0){ //채팅방 생성 페이지
		member_list = [$('#user').attr('data-id')];
	}else if($('#talkDetail').length>0){ //채팅 페이지
		//웹소켓 연결 후 코드 입력 (웹소켓 인식 후 데이터 넣어주는 과정 추가)
	}
	
	
	/*--------------------------
	*	웹소켓 연결
	* --------------------------*/
	
	
	
	/*--------------------------
	*	채팅하기
	* --------------------------*/	
	
});

1.
if($('#talkWrite').length>0){ //채팅방 생성 페이지
jquery는 기본적으로 모두 배열로 인식함
그래서 length로 해당 아이디가 존재하는지 안하는지 판단함

 

member_list = [$('#user').attr('data-id')];
그래서 아이디가 있을 시에 member_list에 id넣음

 

2.

#talkDetail 은 채팅 안의 페이지인데 아직 구현하지 않았기 때문에 비워놓음

 

 

 

 

 

 

채팅 멤버 검색하는 SQL문 작성

kr.spring.member.dao

MemberMapper.java

//채팅 회원이름 검색
@Select("SELECT mem_num,id,nick_name FROM spmember WHERE auth >= 2 AND id LIKE '%' || #{id} || '%'") //일반회원이상+유사ID검색
public List<MemberVO> selectSearchMember(String id);

member를 검색해서 채팅방에 추가해야 하기 때문에 MemberMapper에 메서드 추가

 

 

 

 

 

 

서비스 파일에도 코드 작성

MemberService.java

//채팅 회원이름 검색
public List<MemberVO> selectSearchMember(String id);

 

 

MemberServiceImpl.java

/*-----------------채팅 회원 이름 검색----------------------*/
@Override
public List<MemberVO> selectSearchMember(String id) {
    return memberMapper.selectSearchMember(id);
}

 

 

 

 

 

 

컨트롤러에서 memberService 기재

TalkController

/* ============================
 * 채팅방 생성
 * ============================*/
//채팅방 생성폼 호출
@GetMapping("/talk/talkRoomWrite")
public String talkRoomWrite() {
    return "talkRoomWrite"; //tiles설정
}
//전송된 데이터 처리

//채팅 회원 검색
@RequestMapping("/talk/memberSearchAjax")
@ResponseBody
public Map<String,Object> memberSearchAjax(@RequestParam String id,
                                           HttpSession session){
    Map<String,Object> mapJson = new HashMap<String,Object>();

    //로그인이 되어있어야 하기 때문에 session에서 정보 꺼내오기
    MemberVO user = (MemberVO)session.getAttribute("user");
    if(user==null) {//로그인이 되지 않은 경우
        mapJson.put("result", "logout");
    }else {//로그인이 된 경우
        List<MemberVO> member = memberService.selectSearchMember(id); //id를 목록으로 읽어옴
        mapJson.put("result", "success");
        mapJson.put("member", member);
    }
    return mapJson;
}

1.

채팅 회원 검색은 한 화면에서 동작되어야 하는거기 때문에 ajax로 보냄

@RequestMapping("talk/memberSearchAjax")

@ResponseBody 작성

 

2.

List<MemberVO> member = memberService.selectSearchMember(id);

id를 목록으로 읽어옴

ex) dragon 검색 -> id, nick_name, mem_num 등 모두 다 목록/list 로 가져옴

 

 

 

 

 

 

js파일 수정하기

js

message.talk.js

/*--------------------------
*	채팅방 생성하기
* --------------------------*/
//회원 정보 검색
$('#member_search').keyup(function(){
	
    //공백일 시
    if($('#member_search').val().trim()==''){
        $('#search_area').empty();
        return;
    }
    
    //서버와 통신
    $.ajax({
        url:'memberSearchAjax',
        type:'post',
        data:{id:$('#member_search').val()},
        dataType:'json',
        success:function(param){
            if(param.result == 'logout'){
                $('#member_search').attr('disabled',true);
                $('#member_search').val('로그인해야 회원검색이 가능합니다');
            }else if(param.result == 'success'){
                $('#search_area').empty();
                $(param.member).each(function(index,item){
                    //채팅방 개설자의 아이디와 동일한 아이디 체크
                    if(!member_list.includes(item.id)){
                        //채팅방 개설자의 아이디와 같지 않은 아이디만 표시
                        let output = '';
                        output += '<li data-num="'+item.mem_num+'">';	
                        output += item.id; //보이는건 id 처리는 mem_num
                        output += '</li>';
                        $('#search_area').append(output);
                    }
                });
            }else{
                alert('회원 검색 오류 발생');
            }
        },	
        error:function(){
            alert('네트워크 오류 발생');
        }		
    });
});

1.

url >> memberSearchAjax

#member_search.val()에 입력된 id 데이터를 post / json 으로 전송

 

2.

logout일 경우 검색창 비활성화, 문구 출력

 

3.

success시

1) #search_area 비우기

2) 반복문을 통해 (index=순서, item=data) member_list에 item.id(개설자 아이디)가 아니라면

output += item.id (보이는 값) / data-num = item.mem_num (실제 전송되는 값)

3) talkRoomWrite.jsp 의 ul id="search_area" 여기에 append함

 

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

restart 후 채팅회원검색 시
아래에 like 로 포함되는 아이디가 검색됨
(자기 자신 아이디는 표시 안됨)

 

 

 

 

 

 


 

 

 

 

 

 

<채팅 상대 선택하는 이벤트 연결>

 

 

 

 

js

message.talk.js

//검색된 회원 선택하기
$(document).on('click','#search_area li',function(){
    let id = $(this).text(); //선택한 아이디 (겉으로 보여지는 용도)
    let mem_num = $(this).attr('data-num'); //선택한 회원 번호 (내부적으로 사용되는 용도)
    member_list.push(id);

    //선택한 id를 화면에 표시
    let choice_id = '<span class="member-span" data-id="'+id+'">';
        choice_id += '<input type="hidden" name="members" value="'+mem_num+'">';
        choice_id += id + '<sup>&times;</sup></span>';

    $('#talk_member').append(choice_id);
    $('#member_search').val('');
    $('#search_area').empty(); //ul태그 초기화

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

//채팅방 이름 생성
function makeRoom_name(){
    let name = '';
    $.each(member_list,function(index,item){
        if(index>0) name += ',';
        name += item;
    });
    if(name.length>55){
        name = name.substring(0,55) + '...';
    }
    $('#basic_name').val(name);
    $('#name_span').text(name);
}

1.
$(document).on('click','#search_area li',function(){
아이디가 표시되는 li태그가 동적으로 생성되었기 때문에 $(document) 사용
#search_area 의 후손선택자 li라 띄움

2.
choice_id 에 span태그 넣기

 

choice_id += id + '×';
선택한 아이디 삭제 하기 위해 넣었음
× << 얘가 X 표시


span = id + x (선택해제) 가 보이고 hidden값으로 mem_num이 보내짐

3.
채팅방 이름 자동 설정 시
makeRoom_name(); 채팅방 이름 자동으로 만들어주는 함수 실행

 

4.

makeRoom_name함수

member_list 반복해서 name 투입 index가 0보다 크면 += ,


name = name.substring(0,55) + '...';
방 이름이 너무 길어지는걸 방지하기 위해 name이 55자 이상이면 ... 으로 생략

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


restart 후 마이페이지 > 채팅 실행 후
회원검색 + 아이디 클릭 시 선택된 아이디가 화면에 표시됨
X 버튼과 전송은 아직 안했음 그냥 표시만 되면 됨

 

아이디를 클릭하면 (채팅방 이름 자동생성 체크 시)
채팅방 이름 >> dragon,lkdsjls,abc123 (자동생성) 이런 식으로 본인id+타인id 형태로 만들어짐

member_list에 없어야 검색이 되게끔 해놨기 때문에 만약 abc123(타인)을 추가한 후

또 같은 타인을 검색했을 때엔 검색창에 abc123이 안 뜸

 

 

 


 

 

 

 

 

<채팅방 이름 수동생성>

 

 

 

자동생성 체크를 풀 시에는 입력칸에서 입력할 수 있게 처리

message.talk.js

//채팅방 이름 생성 방식 정하기(자동/수동)
$('#name_checked').click(function(){
    if($('#name_checked').is(':checked')){ //채팅방 이름 자동 생성
        $('#basic_name').attr('type','hidden');
        if(member_list.length>1){ //자기자신(1)
            makeRoom_name();
        }
    }else{//채팅방 이름 수동생성
        $('#basic_name').attr('type','text');
        $('#name_span').text(''); //채팅방 이름 표시 텍스트 초기화
    }
});

 

채팅방 자동생성 선택 후 선택 해제 시 기본값으로 id(hidden값)이 보이고 입력할 수 있게 됨
채팅방 자동생성 처음부터 미 선택 시 hidden값이 없기 때문에 빈칸 표시

 

 

 

728x90
반응형