학원/spring

1.23 (tiles-댓글 수정,삭제,duration / 채팅 테이블 생성)

쿠룽지 2024. 1. 23. 21:55
728x90
반응형

 

 

 

 

<복습>

 

 

1.

댓글 작업 순서

mapper에서 SQL문 작성 -> controller 에서 호출 -> board.reply.js 에서 ajax 코드 작성

 

 

2.

output += ' <input type="button" data-num="'+item.re_num+'" value="수정" class="modify-btn">';
output += ' <input type="button" data-num="'+item.re_num+'" value="삭제" class="delete-btn">';

여기 input 앞에 ('와 < 사이에) 공백을 줬기 때문에 공백이 그대로 생기면서 수정삭제 버튼 사이에 공간이 생김

 

 

 

 


 

 

 

 

 

<댓글 수정폼 생성>

 

 

 

 

 

한건의 데이터 읽어오는 메서드 + update 메서드 sql문 작성

BoardMapper.java

//댓글 수정,삭제 시 작성자 회원번호 구할 때 사용
@Select("SELECT * FROM spboard_reply WHERE re_num=#{re_num}")
public BoardReplyVO selectReply(int re_num); //한건의 데이터 읽어오기

@Update("UPDATE spboard_reply SET re_content=#{re_content}, re_ip=#{re_ip}, re_mdate=SYSDATE WHERE re_num=#{re_num}")
public void updateReply(BoardReplyVO boardReply);

1.
작성자 회원번호 구하기 위함


2.
업데이트를 위한 구문

 

 

 

 

 

 

Service파일에서 호출

BoardServiceImpl

@Override
public BoardReplyVO selectReply(int re_num) {
    return boardMapper.selectReply(re_num);
}


@Override
public void updateReply(BoardReplyVO boardReply) {
    boardMapper.updateReply(boardReply);
}

 

 

 

 

 

ajaxController에서 작성

BoardAjaxController

/*=============================
*    댓글 수정
============================*/
@RequestMapping("/board/updateReply")
@ResponseBody
public Map<String,String> modifyReply(BoardReplyVO boardReplyVO,
                                     HttpSession session,
                                     HttpServletRequest request){
   log.debug("<<댓글 수정 BoardReplyVO>> : " + boardReplyVO);

   Map<String,String> mapJson = new HashMap<String,String>();




   return mapJson;
}

 

 

 

 

 

 

 

jquery로 댓글 수정 폼 생성하기

수정 버튼 클릭 시 기존 content 위치에 폼이 생성되는 방식으로 수행

board.reply.js

	/*----------------------
	        댓글 수정
	------------------------*/	
	//댓글 수정 버튼 클릭 시 수정폼 노출
	$(document).on('click','.modify-btn',function(){
		//댓글 번호 구하기
		let re_num = $(this).attr('data-num');
		//댓글 내용 구하기
		let content = $(this).parent().find('p').html().replace(/<br>/gi,'\r\n');
		
		//댓글 수정폼 UI 생성
		let modifyUI = '<form id="mre_form">';
			modifyUI += '<input type="hidden" name="re_num" id="mre_num" value="'+re_num+'">';
			modifyUI += '<textarea rows="3" cols="50" name="re_content" id="mre_content" class="rep-content">'+content+'</textarea>';
			modifyUI += '<div id="mre_first"><span class="letter-count">300/300</span></div>';
			modifyUI += '<div id="mre_second" class="align-right">';
			modifyUI += ' <input type="submit" value="수정">';
			modifyUI += ' <input type="button" value="취소" class="re-reset">';
			modifyUI += '</div>';
			modifyUI += '<hr size="1" noshade width="96%">';
			modifyUI += '</form>';
			
		//이전에 이미 수정하는 댓글이 있을 경우 수정 버튼을 클릭하면
		//숨김 sub-item을 환원시키고, 수정폼을 초기화
		initModifyForm();
		//지금 클릭해서 수정하고자 하는 데이터는 감추기
		//수정 버튼을 감싸고 있는 div를 감추기
		$(this).parent().hide();
		
		//수정폼을 수정하고자 하는 데이터가 있는 div에 노출
		$(this).parents('.item').append(modifyUI); //sub_item은 숨겨지기 때문에 부모태그에 붙임	
		
		//입력한 글자수 셋팅
		let inputLength = $('#mre_content').val().length;
		let remain = 300 - inputLength;
		remain += '/300';
		
		//문서 객체에 반영
		$('#mre_first .letter-count').text(remain);
			
	});
	
	//수정폼에서 취소 버튼 클릭 시 수정폼 초기화
	$(document).on('click', '.re-reset',function(){
		initModifyForm();
	});
	//댓글 수정폼 초기화
	function initModifyForm(){
		$('.sub-item').show();
		$('#mre_form').remove();
	}

1.
$(document).on('click','.modify-btn',function(){});
수정, 삭제버튼이 기존 jsp 파일에 본래 없고 동적으로 js 파일에 만든거라 이벤트를 document로 연결

2.
replace(/<br>/gi,'\r\n');
아까 위에서 줄바꿈을 위해 br태그를 만들었기 때문에 모든 br을 다시 바꾸는 거임

3.
modifyUI += '<input type="hidden" name="re_num" id="mre_num">'
위 댓글 번호 구할때의 id와 중복되지 않게 하려고 m을 붙임 (mre_content, mre_first도 동일한 이유)

class는 겹쳐도 상관x

4.
댓글 창을 여러개 수정시키는걸 막기위해 하나  누른 상태에서 다른걸 또 누르면 처음에 누른 폼을 초기화 시키기 위해 initModifyForm을 만들어서 활용할거임

5.
$(this).parents('.item').append(modifyUI);
수정하고자 하는 데이터가 있는 부모'들'에 붙이기 위해 parents 사용


수정버튼 수정폼 열림!

 

 

 

 

 


 

 

 

 

 

<댓글 수정기능 구현>

 

 

 

 

 

AjaxController 코드 작성

BoardAjaxController

/*=============================
*    댓글 수정
============================*/
@RequestMapping("/board/updateReply")
@ResponseBody
public Map<String,String> modifyReply(BoardReplyVO boardReplyVO,
                                     HttpSession session,
                                     HttpServletRequest request){
   log.debug("<<댓글 수정 BoardReplyVO>> : " + boardReplyVO);

   Map<String,String> mapJson = new HashMap<String,String>();

   MemberVO user = (MemberVO)session.getAttribute("user");
   BoardReplyVO db_reply = boardService.selectReply(boardReplyVO.getRe_num());

   if(user==null) {
       //로그인이 되지 않은 경우
       mapJson.put("result", "logout");
   }else if (user!=null && user.getMem_num()==db_reply.getMem_num()){
       //로그인한 회원번호와 작성자 회원번호가 일치

       //ip 등록
       boardReplyVO.setRe_ip(request.getRemoteAddr());
       //댓글 수정
       boardService.updateReply(boardReplyVO);
       mapJson.put("result", "success");
   }else {
       //로그인한 회원번호와 작성자 회원번호가 불일치
       mapJson.put("result", "wrongAccess");
   }
   return mapJson;
}

 

 

 

 

 

 

댓글 수정 js코드 작성

board.reply.js

//댓글 수정
$(document).on('submit','#mre_form',function(event){
    if($('#mre_content').val().trim()==''){
        alert('내용을 입력하세요');
        $('#mre_content').val('').focus();
        return false;
    }
    //폼에 입력한 데이터 반환
    let form_data = $(this).serialize();

    //서버와 통신
    $.ajax({
        url:'updateReply',
        type:'post',
        data:form_data,
        dataType:'json',
        success:function(param){
            if(param.result=='logout'){
                alert('로그인해야 수정할 수 있습니다.');
            }else if(param.result=='success'){
                //내용 읽기
                $('#mre_form').parent().find('p').html($('#mre_content').val().replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\r\n/g,'<br>').replace(/\r/g,'<br>').replace(/\n/g,'<br>'));
                //최근 수정일 처리
                $('#mre_form').parent().find('.modify-date').text('최근 수정일 : 5초미만');
                //수정폼 초기화
                initModifyForm();

            }else if(param.result=='wrongAccess'){
                alert('타인의 글은 수정할 수 없습니다.');
            }else{
                alert('댓글 수정 오류');
            }
        },
        error:function(){
            alert('네트워크 오류 발생');
        }
    });
    //기본 이벤트 제거
    event.preventDefault();
});

1.
$('#mre_form').parent().find('p').html($('#mre_content').val().replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\r\n/g,'<br>').replace(/\r/g,'<br>').replace(/\n/g,'<br>'));
p태그를 찾아서 변경할 내용을 그 안에 html로 셋팅

서버에 저장 후 읽어오는 게 아니라 화면에 입력 후 읽어오는거기 때문에 html 불허 처리를 해야함






댓글 수정하는 방법 (정리)
1. db에 보내고 select해서 한건 읽어온 후 그걸 화면 출력 (저장했던 데이터 다시 읽어오는 방법)
2. db access로 굳이 안받아오고 그냥 화면갱신으로 불러오기

이렇게 2가지 방법이 있는데 2번이 덜 번거롭고 좋다고 하심

 

 

 

 

 

 


 

 

 

 

 

<댓글 삭제기능 구현>

 

 

 

 

 

삭제 sql문 작성

BoardMapper.java

@Delete("DELETE FROM spboard_reply WHERE re_num=#{re_num}")
public void deleteReply(int re_num);

 

 

 

 

 

Service에서 호출

BoardServiceImpl

@Override
public void deleteReply(int re_num) {
    boardMapper.deleteReply(re_num);
}

 

 

 

 

 

Controller 작성

BoardAjaxController

/*=============================
*    댓글 삭제
============================*/
@RequestMapping("/board/deleteReply")
@ResponseBody
public Map<String,String> deleteReply(@RequestParam int re_num,
                                     HttpSession session){
   log.debug("<<댓글 삭제 re_num>> : " + re_num);

   Map<String,String> mapJson = new HashMap<String,String>();

   MemberVO user = (MemberVO)session.getAttribute("user");
   BoardReplyVO db_reply = boardService.selectReply(re_num);
   if(user==null) {
       //로그인이 되지 않은 경우
       mapJson.put("result", "logout");
   }else if(user!=null && user.getMem_num()==db_reply.getMem_num()) {
       //로그인한 회원번호와 작성자 회원번호가 일치
       boardService.deleteReply(re_num);
       mapJson.put("result", "success");
   }else {
       //로그인한 회원번호와 작성자 회원번호가 불일치
       mapJson.put("result", "wrongAccess");
   }
   return mapJson;
}

 

 

 

 

 

 

js 작성

board.reply.js

/*----------------------
    댓글 삭제
------------------------*/
$(document).on('click','.delete-btn',function(){
    //댓글 번호 구하기
    let re_num = $(this).attr('data-num');

    //서버와 통신
    $.ajax({
        url:'deleteReply',
        type:'post',
        data:{re_num:re_num},
        dataType:'json',
        success:function(param){
            if(param.result=='logout'){
                alert('로그인해야 삭제할 수 있습니다.');
            }else if(param.result=='success'){
                alert('삭제 완료!');
                selectList(1);
            }else if(param.result=='wrongAccess'){
                alert('타인의 글을 삭제할 수 없습니다.');
            }else{
                alert('댓글 삭제 오류 발생');
            }
        },
        error:function(){
            alert('네트워크 오류 발생!')
        }
    });

});

1.
data:{re_num:re_num},
앞 re_num=key 뒤 re_num=value
뒤 re_num은 위에서 명시한 변수임

2.
selectList(1);
첫 페이지 호출


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

restart 후 누르면 삭제+alert창 뜸

 

 

 

 


 

 

 

 

<추가기능-Duration 처리>

 

 

 

mbox에서 duration 클래스 내려받고 kr.spring.util에 복붙

kr.spring.board.vo

BoardReplyVO

package kr.spring.board.vo;

import kr.spring.util.DurationFromNow;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class BoardReplyVO {
	private int re_num;
	private String re_content;
	private String re_date;
	private String re_mdate; //연월일시분초가 아니라 하루전 이틀전 이렇게 변환 작업할거라서 string 처리
	private String re_ip;
	private int board_num;
	private int mem_num;
	
	private String id;
	private String nick_name;
	
	//작성
	public void setRe_date(String re_date) {
		this.re_date = DurationFromNow.getTimeDiffLabel(re_date);
	}
	//수정
	public void setRe_mdate(String re_mdate) {
		this.re_mdate = DurationFromNow.getTimeDiffLabel(re_mdate);
	}
}

restart 후
최근 수정일 : 14초 전
이런식으로 시간이 바껴서 나옴

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

 

<깨알 정리>

 

 


부모글에 자식글이 있을 시에는 특히 주의해야함
ServiceImpl 안 메서드를 보면

@Override
public void deleteBoard(int board_num) {
//부모글 좋아요 삭제
boardMapper.deleteFavByBoardNum(board_num);
//댓글이 존재하면 댓글을 우선 삭제하고 부모글 삭제
boardMapper.deleteReplyByBoardNum(board_num);
//부모글 삭제
boardMapper.deleteBoard(board_num);
}


이런식으로 다 처리를 해놓음



게시판 끝

 

 


 

 

 

<채팅 시작>




그룹채팅
id검색 시 초대해서 그룹으로 채팅하는 형식
nickname반영 X id중심으로 진행




테이블 생성
sql
table.sql

--채팅방
create table sptalkroom(
 talkroom_num number not null,
 basic_name varchar2(900) not null, --기본 채팅방 이름
 talkroom_date date default SYSDATE not null,
 constraint sptalkroom_pk primary key (talkroom_num)
);

create sequence sptalkroom_seq;


--채팅방 멤버 (구성원)
create table sptalk_member(
 talkroom_num number not null,
 mem_num number not null,
 room_name varchar2(900) not null, --멤버별 채팅방 이름 (방 이름 변경 시 roon_name 사용)
 member_date date default SYSDATE not null,
 constraint sptalk_member_fk1 foreign key (talkroom_num) references sptalkroom (talkroom_num),
 constraint sptalk_member_fk2 foreign key (mem_num) references spmember (mem_num)
);


--채팅(메시지) 테이블
create table sptalk(
 talk_num number not null,
 talkroom_num number not null, --메시지 받는 수신 그룹
 mem_num number not null, --발신자
 message varchar2(4000) not null,
 chat_date date default SYSDATE not null,
 constraint sptalk_pk primary key (talk_num),
 constraint sptalk_fk1 foreign key (talkroom_num) references sptalkroom (talkroom_num),
 constraint sptalk_fk2 foreign key (mem_num) references spmember (mem_num)
);

create sequence sptalk_seq;


--채팅 메시지 확인 (읽었는지 안 읽었는지 체크하는 테이블)
create table sptalk_read(
 talkroom_num number,
 talk_num number not null,
 mem_num number not null,
 constraint read_fk1 foreign key (talkroom_num) references sptalkroom (talkroom_num),
 constraint read_fk2 foreign key (talk_num) references sptalk (talk_num),
 constraint read_fk3 foreign key (mem_num) references spmember (mem_num)
);

sptalk_read
여러명에 대해 읽었는지 안읽었는지 체크하려면 테이블이 별도로 필요함

728x90
반응형