<채팅방 생성>
웹소켓을 사용해서 실시간 채팅을 만들 예정
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>×</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값이 없기 때문에 빈칸 표시
'학원 > spring' 카테고리의 다른 글
1.26 (tiles-채팅방 목록보기, 상세) (0) | 2024.01.28 |
---|---|
1.25 (tiles-그룹채팅 멤버 초대, 채팅방 생성) (0) | 2024.01.25 |
1.23 (tiles-댓글 수정,삭제,duration / 채팅 테이블 생성) (0) | 2024.01.23 |
1.22 (tiles-댓글 작성, 목록 처리/더보기 버튼) (0) | 2024.01.22 |
1.19 (tiles-좋아요 구현, 댓글 기본 설정+ui) (1) | 2024.01.21 |