✿∘˚˳°∘°
81일차 : ajax, 에러처리, 웹소켓 본문
20230324
1. Ajax
ajax사용을 위한 GSON라이브러리 추가
<!-- GSON 라이브러리 추가 -->
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
1 - 1 ) 비밀번호 변경
요즘 비밀번호는 마이페이지에서 바로변경X 암호화때문에 굉장히 복잡하기 때문이다.
그러므로 비밀번호 변경페이지를 새로 만들어줄 것
수정한 mypage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>마이페이지</h1>
<hr>
<form action="/updateMember.do" method="post">
<fieldset>
<legend>회원정보</legend>
회원번호 : <input type="text" name="memberNo" value="${sessionScope.m.memberNo }" readonly><br>
아이디 : <input type="text" name="memberId" value="${sessionScope.m.memberId }" readonly><br>
비밀번호 : <button type="button" onclick="pwChange();">비밀번호 변경하기</button><br>
<%-- 비밀번호 : <input type="password" name="memberPw" value="${sessionScope.m.memberPw }" ><br>--%>
이름 : <input type="text" name="memberName" value="${sessionScope.m.memberName }" readonly><br>
전화번호 : <input type="text" name="memberPhone" value="${sessionScope.m.memberPhone }"><br>
이메일 : <input type="text" name="memberEmail" value="${sessionScope.m.memberEmail }" ><br>
<input type="submit" value="정보수정">
</fieldset>
</form>
<a href="/">메인으로</a>
<script>
function pwChange(){
location.href="/pwChangeFrm.do";
}
</script>
</body>
</html>
비밀번호변경페이지 pwChange.jsp(여기서 페이지이동없이 ajax로 데이터를 처리해줄것)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.6.1.js"></script>
<style>
#pwChangeFrm{
display: none;
}
</style>
</head>
<body>
<h1>비밀번호 변경</h1>
<hr>
현재 비밀번호 입력 : <input type="password" name="currentPw">
<button type="button" id="checkBtn">입력</button>
<%--현재 비밀번호를 입력해서 ajax를 통해 확인 후 비밀번호가 맞을 경우에 form태그를 보여줄것 --%>
<form action="/pwChange.do" method="post" id="pwChangeFrm">
<input type="hidden" name="memberId" value="${sessionScope.m.memberId }">
비밀번호 : <input type="password" name="memberPw"><br>
비밀번호 확인 : <input type="password" name="memberPwRe"><br>
<input type="submit" value="비밀번호 변경하기" onclick="return checkPw();">
</form>
<script>
$("#checkBtn").on("click", function(){
const memberPw = $("[name=currentPw]").val();
const memberId = $("[name=memberId]").val();
$.ajax({
url : "/pwCheck.do",
type : "post",
data : {memberId:memberId, memberPw:memberPw},
success : function(data){
if(data == "ok"){
$("#pwChangeFrm").slideDown();
}else{
alert("비밀번호를 확인하세요");
}
},
error : function(){
console.log("실패");
}
});
});
function checkPw(){
const pw = $("[name=memberPw]").val();
const pwRe = $("[name=memberPwRe]").val();
if(pw != pwRe){
alert("비밀번호를 확인하세요.")
return false;
}
}
</script>
</body>
</html>
ajax에서 이동하는 Controller
//페이지 이동이 아닌 값 자체를 return하는 코드가 된다.
@ResponseBody
@RequestMapping(value="/pwCheck.do")
public String pwCheck(Member member) {
//아이디&패스워드로 회원을 조회해주는 로그인 로직을 이용할것 -> 암호화도 된다
Member m = service.selectOneMember(member);
if(m != null) {
//상단에 ResponseBody를 붙여줬으므로 페이지이동X 값만 넘겨준다.
return "ok";
}else {
return "error";
}
}
실제 비밀번호 update를 진행할 Controller
@RequestMapping(value="/pwChange.do")
public String pwChange(Member member, String memberPwRe) {
int result = service.updateMemberPw(member, memberPwRe);
if(result > 0) {
return "redirect:/";
}else {
return "redirect:/updateMember.do";
}
}
Service - update이기 때문에 트랜잭션관리를 해줄 것
@Transactional
public int updateMemberPw(Member member, String memberPwRe) {
return dao.updateMemberPw(member);
}
Dao
public int updateMemberPw(Member member) {
int result = sqlSession.update("member.pwChangeMember", member);
return result;
}
memberSQL
<update id="pwChangeMember" parameterType="m">
update member_tbl set member_pw = #{memberPw} where member_id = #{memberId}
</update>
1 - 2 ) 회원가입 시 아이디 중복체크
추가한 joinFrm.jsp - 아이디 input태그 옆에 span태그를 추가하고 ajax코드를 추가하였다
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.6.1.js"></script>
</head>
<body>
<h1>회원가입</h1>
<hr>
<form action="/join.do" method="post">
<fieldset>
<legend>회원가입</legend>
아이디 : <input type="text" name="memberId"><span id="idChk"></span><br>
비밀번호 : <input type="password" name="memberPw"><br>
이름 : <input type="text" name="memberName"><br>
전화번호 : <input type="text" name="memberPhone"><br>
이메일 : <input type="text" name="memberEmail"><br>
<input type="submit" value="회원가입">
<input type="reset" value="취소">
</fieldset>
</form>
<a href="/">메인으로</a>
<script>
$("[name=memberId]").on("change", function(){
const memberId = $(this).val();
$.ajax({
url : "/idCheck.do",
type : "get",
data : {memberId : memberId},
success : function(data){
if(data == "ok"){
$("#idChk").text("사용 가능한 아이디 입니다.");
$("#idChk").css("color", "blue");
}else{
$("#idChk").text("이미 사용중인 아이디 입니다.");
$("#idChk").css("color", "red");
}
}
});
});
</script>
</body>
</html>
ajax에서 이동하는 Controller
@ResponseBody
@RequestMapping(value="/idCheck.do")
public String idCheck(Member member) {
//매개변수를 String memberId로 받아도 된다
//Member를 사용하는 이유는 Service에서 메소드를 재사용하려고(아이디찾는 메소드가 이미 있기때문에)
Member m = service.selectOneMemberId(member);
if( m == null ) {
//아이디 사용가능
return "ok";
}else {
//아이디 중복
return "dup";
}
}
1 - 3 ) ajax로 전체회원 조회하기(객체를 받기)
객체를 받기 위해서는 GSON이 필요, 이를 위에 제일처음 라이브러리를 추가해줬다.
index.jsp에 추가한 코드
<button id="allMemberAjax">전체회원조회</button>
<div id="ajaxResult"></div>
<script>
$("#allMemberAjax").on("click", function(){
$.ajax({
url : "/ajaxAllMember.do",
//ajax요청에 의한 데이터를 되돌려 줄 때 문제점2
//1. 문자열 형식 -> 객체로변경
//ajax에서 json을 선언해줘도되지만 이러면 한글이 깨짐 -> 따로인코딩을 해줘야함
//2. 한글깨짐
//이 두가지를 동시에 해결하기 위해 Controller에서 진행
success : function(data){
$("#ajaxResult").empty();
const table = $("<table>");
const titleTr = $("<tr>");
titleTr.html("<th>번호</th>th>아이디</th>th>이름</th>th>전화번호</th>");
table.append(titleTr);
for(let i=0; i<data.length; i++){
const tr = $("<tr>");
tr.append("<td>"+data[i].memberNo+"</td>");
tr.append("<td>"+data[i].memberId+"</td>");
tr.append("<td>"+data[i].memberName+"</td>");
tr.append("<td>"+data[i].memberPhone+"</td>");
table.append(tr);
}
$("#ajaxResult").append(table);
}
});
});
</script>
ajax에서 이동하는 Controller
//application/json;charset=utf-8 되돌려주는타입이 Json이고 한글타입임을 명시
@ResponseBody
@RequestMapping(value="/ajaxAllMember", produces = "application/json;charset=utf-8")
public String ajaxAllMember() {
ArrayList<Member> list = service.selectAllMember();
Gson gson = new Gson();
String result = gson.toJson(list);
System.out.println(result);
return result;
}
2. 에러처리 ( 많이 본 에러 : 500, 400, 404 )
Http Response.Status
[ 2xx ] -> 정상적으로 페이지가 떳을 때
200 ok
[ 3xx ] -> redirect
----------------------------------------------------------------------
[ 4xx ] -> 클라이언트가 잘못한 거
400 -> bad request(잘못된 요청)
404 -> not found(사용자가 잘못하는 경우, 개발자잘못)
-> 1) Controller를 잘못요청하는 경우(주소창잘못요청)
: 사용자가 잘못했을 수도 있고, 개발중에 실수가 있을 수도 있음
(사용자의 잘못일 수도 있으니 에러페이지로 처리)
-> 2) Controller에서 리턴하는 JSP를 만들지 않았거나 오타가 있는 경우
: 100% 개발자의 실수 -> 에러페이지로 처리하면 안됨 -> 소스코드수정
[ 5xx ] -> 서버에서 에러난거
500 -> 정보가 유출가능성이 있음 -> 소스코드 수정
502 -> bad gateway(서버터졌을때) : 그냥 에러페이지를 띄우느 사이트도 있지만
접속자가 많다는 페이지로 빼는 사이트도 있다.
404와 500은 발생하면 안되므로 에러처리를 해줄 것
처리하는 방법
우선 web.xml 의 <servlet></servlet> 사이에 에러관련 설정을 추가해준다.
<servlet>
<!-- 프로젝트 생성 시 기본 설정 -->
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<!-- 에러처리를 위한 추가 설정 -->
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
에러 관련 class
package common;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;
//@Component를 포함하고 있는 annotation이기 때문에 이걸 붙여놔도 객체생성O
//@Controller annotation이 포함되어있는 객체에서 에러가 발생했을 때 처리하는 annotation
@ControllerAdvice
public class ErrorUtil {
@ExceptionHandler(Exception.class)
public String handelException(Exception e) {
//오류마다 다르게 처리할거면 여러개 생성하면된다.
System.err.println("에러발생");
//out으로 해도되지만 색 바꾸려고 err
System.err.println(e.getMessage());
return "error/error1";
}
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(value = HttpStatus.NOT_FOUND) //응답상태가 not_found(404) 오류
public String notFound(NoHandlerFoundException e) {
System.err.println("RequestMapping 오류");
System.err.println(e.getMessage());
return "error/error2";
}
}
error1.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>서버에서 에러가 발생했습니다.</h1>
<hr>
<h3>잠시후 다시 시도해주세요</h3>
<a href="/">메인페이지로</a>
</body>
</html>
error2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>요청 에러 발생</h1>
<hr>
<a href="/">메인으로</a>
</body>
</html>
코드를 짜는 단계에서는 에러확인을 해야하기때문에, 완성 후 에러처리작업을 해주는것이 좋다.
3. 웹소켓
웹소켓 사용을 위한 라이브러리 추가 - pom.xml
<!-- Websocket사용을 위한 라이브러리(spring-websocket, jackson-databind) -->
<!-- spring-websocket은 spring버전과 맞춰줘야한다. -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.5</version>
</dependency>
servlet-context의 namespace 탭에서 웹소켓 선택

servlet-context의 source에서 웹소켓을 처리할 객체 생성
<!-- 웹소켓 채팅을 처리할 객체 생성 -->
<beans:bean id="allMemberChat" class="common.AllMemberChat" />
<!-- 웹소켓 매핑 -->
<websocket:handlers>
<websocket:mapping handler="allMemberChat" path="/chat.do"/>
</websocket:handlers>
3 - 1 ) 채팅
채팅 페이지 이동
<h3><a href="/allMemberChat.do">전체채팅</a></h3>
@RequestMapping(value="/allMemberChat.do")
public String allMemberChat() {
return "member/allMemberChat";
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.6.1.js"></script>
<style>
.chatting{
width: 500px;
display: none;
}
<%-- y축으로 내부컨텐츠가 넘어가면 스크롤생성 --%>
.messageArea{
overflow-y : auto;
border: 1px solid black;
height: 500px;
display: flex;
flex-direction: column;
background-color: #b2c7d9;
}
.messageArea>p{
text-align: center;
width: 100%;
}
#sendMsg{
width: 75%;
}
#sendBtn{
width:20%;
}
.chat{
margin-bottom: 10px;
padding: 8px;
border-radius: 3px;
}
.left{
position: relative;
max-width: 300px;
align-self: flex-start;
background-color: #fff;
border-radius: 10px;
margin-left: 16px;
padding: 15px;
}
.left:after{
content:'';
position: absolute;
border-style: solid;
border-width: 15px 15px 15px 0;
border-color: transparent #fff;
display: block;
width: 0;
z-index: 1;
left: -15px;
top: 12px;
}
.right{
position: relative;
max-width: 300px;
align-self: flex-end;
background-color: #ffeb33;
border-radius: 10px;
margin-right: 16px;
padding: 15px;
}
.right:after{
content:'';
position: absolute;
border-style: solid;
border-width: 15px 0 15px 15px;
border-color: transparent #ffeb33;
display: block;
width: 0;
z-index: 1;
right: -15px;
top: 12px;
}
</style>
</head>
<body>
<h1>전체채팅</h1>
<c:if test="${not empty sessionScope.m }">
<button onclick="initChat('${sessionScope.m.memberId}');">채팅시작하기</button>
<div class="chatting">
<div class="messageArea">
</div>
<div class="sendBox">
<input type="text" id="sendMsg">
<button id="sendBtn" onclick="sendMsg();">전송</button>
</div>
</div>
<script>
let ws; //웹소켓 객체를 저장하는 변수
let memberId; // 회원아이디를 저장하는 변수
function initChat(param){
memberId = param;
//웹소켓 연결 시도
//주의점 127.0.0.1 또는 localhost로 사용하면 소켓연결을 할 수 없으므로 반드시 IP로 작성
ws = new WebSocket("ws://192.168.10.17/chat.do");
//웹소켓 연결 성공 시 실행할 함수 지정
ws.onopen = startChat;
//서버에서 데이터를 받으면 처리할 함수 지정
ws.onmessage = receiveMsg;
//웹소켓 연결이 종료되면 실행될 함수 지정
ws.onclose = endChat;
$(".chatting").slideDown();
}
function startChat(){
console.log("웹소켓 연결완료");
const data = {type:"enter", msg: memberId};
//문자열이 넘어가야하는데 data는 Object이기 때문에 에러발생 JSON.stringify(data) 형태로 보내줘야한다
console.log(JSON.stringify(data));
ws.send(JSON.stringify(data));
appendChat("<p>채팅방에 입장했습니다.</p>");
}
function receiveMsg(param){
console.log(param);
appendChat(param.data);
}
function endChat(){
console.log("웹소켓 연결종료");
}
function sendMsg(){
const msg = $("#sendMsg").val();
if(msg != ''){
const data = {type:"chat", msg:msg}
ws.send(JSON.stringify(data));
appendChat("<div class='chat right'>"+msg+"</div>");
$("#sendMsg").val(''); //input clear
}
}
$("#sendMsg").on("keyup", function(e){
if(e.keyCode == 13){
//keyCode == 13 : enter
sendMsg();
}
});
function appendChat(chatMsg){
$(".messageArea").append(chatMsg);
//스크롤이 생기면 스크롤 위치를 잡아줌
$(".messageArea").scrollTop($(".messageArea")[0].scrollHeight);
}
</script>
</c:if>
<hr>
<a href="/">메인으로</a>
</body>
</html>
채팅 Controller
package common;
import java.util.ArrayList;
import java.util.HashMap;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class AllMemberChat extends TextWebSocketHandler{
//접속한 회원 세션을 저장하는 리스트
private ArrayList<WebSocketSession> sessionList;
//세션에 대한 아이디 mapping
private HashMap<WebSocketSession, String> memberList;
public AllMemberChat() {
super();
sessionList = new ArrayList<WebSocketSession>();
memberList = new HashMap<WebSocketSession, String>();
}
//클라이언트가 웹소켓으로 최초에 접속했을 때 자동으로 수행되는 메소드
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception{
System.out.println("클라이언트 접속");
//최초 접속한 session정보를 세션목록에 추가
sessionList.add(session);
}
//클라이언트가 메세지를 보내면 처리할 메소드
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception{
//System.out.println("session : "+session);
System.out.println("사용자가 전송한 메세지 : "+message.getPayload());
//message.getPayload() : 문자열 형태로 객체데이터를 쓰기 위해서는 JSON형식으로 변환해서 사용해야함
//문자열을 JSON으로 변환할 객체
JsonParser parser = new JsonParser();
JsonElement element = parser.parseString(message.getPayload());
//key가 type인 값을 추출
String type = element.getAsJsonObject().get("type").getAsString();
//key가 msg인 값을 추출
String msg = element.getAsJsonObject().get("msg").getAsString();
System.out.println("type : "+type);
System.out.println("msg : "+msg);
if(type.equals("enter")) {
//최초접속했을 때 memberId가 들어있음
//최초접속이므로 memberList에 정보저장
memberList.put(session, msg);
String sendMsg = "<p>"+msg+"님이 입장하셨습니다.</p>";
//클라이언트 전송용 객체
TextMessage tm = new TextMessage(sendMsg);
for(WebSocketSession s : sessionList) {
if(!s.equals(session)) {
s.sendMessage(tm);
}
}
}else if(type.equals("chat")) {
String sendMsg = "<div class='chat left'><span class='chatId'>"+memberList.get(session)+" : </span>"+msg+"</div>";
TextMessage tm = new TextMessage(sendMsg);
for(WebSocketSession s : sessionList) {
if(!s.equals(session)) {
s.sendMessage(tm);
}
}
}
}
//클라이언트와 연결이 끊어졌을 때 자동으로 수행되는 메소드
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception{
System.out.println("클라이언트 연결 끊김");
//연결이 끊기면 세션목록에서 제거
sessionList.remove(session);
String sendMsg = "<p>"+memberList.get(session)+"님이 나갔습니다.</p>";
TextMessage tm = new TextMessage(sendMsg);
for(WebSocketSession s : sessionList) {
if(!s.equals(session)) {
s.sendMessage(tm);
}
}
memberList.remove(session);
}
}
3 - 2 ) 쪽지
쪽지기능을 위해 DB테이블 생성
-- 쪽지기능
CREATE TABLE DIRECT_MESSAGE(
DM_NO NUMBER PRIMARY KEY,
SENDER VARCHAR2(20) REFERENCES MEMBER_TBL(MEMBER_ID) ON DELETE CASCADE,
RECEIVER VARCHAR2(20) REFERENCES MEMBER_TBL(MEMBER_ID) ON DELETE CASCADE,
DM_CONTENT VARCHAR2(300) NOT NULL,
DM_DATE DATE,
READ_CHECK NUMBER -- 0이면 읽지앖음 1이면 읽음
);
CREATE SEQUENCE DM_SEQ;
VO : DM.class
package kr.or.iei.dm.model.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DM {
private int dmNo;
private String sender;
private String receiver;
private String dmContent;
private String dmDate;
private int readCheck;
}
쪽지 페이지 이동
<h3><a href="/dmMain.do">쪽지함</a></h3>
@RequestMapping(value="/dmMain.do")
public String dmMain() {
return "dm/dmMain";
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="/resources/css/dm.css">
<script src="https://code.jquery.com/jquery-3.6.1.js"></script>
</head>
<body>
<h1>쪽지함</h1>
<hr>
<h3>쪽지보내기</h3>
<button onclick="sendDmModal();">쪽지보내기</button>
<hr>
<h3>받은쪽지함</h3>
<table border="1" class="receiveDmTbl">
<thead>
<tr>
<th>보낸사람</th>
<th>내용</th>
<th>시간</th>
<th>읽음여부</th>
</tr>
</thead>
<tbody></tbody>
</table>
<hr>
<h3>보낸쪽지함</h3>
<table border="1" class="sendDmTbl">
<thead>
<tr>
<th>받은사람</th>
<th>내용</th>
<th>시간</th>
<th>읽음여부</th>
</tr>
</thead>
<tbody></tbody>
</table>
<!-- 쪽지보내기 모달 -->
<div id="sendDm-modal" class="modal-wrapper">
<div class="modal">
<div class="modal-header">
<h2>쪽지보내기</h2>
</div>
<hr>
<div class="modal-content">
<div class="sendDmFrm">
<label>수신자 : </label>
<select name="receiver"></select>
<textarea name="dmContent"></textarea>
<input type="hidden" id="sender" value="${sessionScope.m.memberId }">
<button onclick="dmSend();">쪽지보내기</button>
<button onclick="closeModal();">닫기</button>
</div>
</div>
</div>
</div>
<script src="/resources/js/dm.js"></script>
</body>
</html>
dmMain - css
@charset "UTF-8";
h1{
color: pink;
}
.modal-wrapper{
position: fixed;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.5);
top: 0;
left: 0;
display: none;
justify-content: center;
align-items: center;
}
.modal{
width: 350px;
background-color: #fff;
}
.modal-header{
padding: 10px;
}
.modal-content{
padding: 20px;
}
textarea[name=dmContent]{
width: 100%;
height: 100px;
resize: none;
}
dmMain - js
/**
*
*/
/* 버튼을 클릭하면 회원목록을 아작스로 가져올것*/
/* 회원조회는 memberController에 생성 */
function sendDmModal(){
$.ajax({
url : "/selectAllMemberId.do",
success : function(list){
//이름 중첩을 하지않기 위해
$("[name=receiver]").empty();
for(let i=0; i<list.length; i++){
const option = $("<option>");
option.val(list[i]);
option.text(list[i]);
$("[name=receiver]").append(option);
}
$("#sendDm-modal").css("display", "flex");
}
});
}
function closeModal(){
$("#sendDm-modal").hide();
//내용도 전부 삭제해줘야함
$("textarea[name=dmContent]").val("");
}
function dmSend(){
//sender receiver dmcotnent를 받아올 것
const receiver = $("[name=receiver]").val();
const sender = $("#sender").val();
const dmContent = $("[name=dmContent]").val();
console.log(receiver, sender, dmContent);
$.ajax({
url : "/insertDm.do",
type : "post",
data : {receiver:receiver, sender:sender, dmContent:dmContent},
success : function(data){
if(data == "0"){
alert("쪽지보내기 실패");
}
closeModal();
}
});
}
function getSendDm(){
const sender = $("#sender").val();
$.ajax({
url : "/myDmList.do",
data : {sender:sender},
success : function(list){
console.log(list);
}
});
}
function getReceiverDm(){
const receiver = $("#sender").val();
$.ajax({
url : "/myDmList.do",
data : {receiver:receiver},
success : function(list){
const tbody = $(".receiveDmTbl>tbody");
tbody.empty();
for(let i=0; i<list.length; i++){
const dm = list[i];
const tr = $("<tr>");
//보낸사람, 내용, 시간 읽음여부
const td1 = $("<td>");
td1.text(dm.sender);
const td2 = $("<td>");
td2.text(dm.dmContent);
const td3 = $("<td>");
td3.text(dm.dmDate);
const td4 = $("<td>");
if(dm.readCheck == 0){
td4.text("읽지않음");
}else{
td4.text("읽음");
}
tr.append(td1).append(td2).append(td3).append(td4);
tbody.append(tr);
}
}
});
}
$(function(){
getReceiverDm();
getSendDm();
});
css와 js위치 webapp/resources 아래 각각 css js 폴더를 만들어서 cssFile/JavaScriptFile생성
쪽지보내기 버튼을 클릭 했을 때 회원들의 ID를 받아올 Controller(기존에 생성해놓았던 Service 사용)
@ResponseBody
@RequestMapping(value="/selectAllMemberId.do", produces = "application/json;charset=utf-8")
public String selectAllMemberId() {
ArrayList<String> list = service.search3();
//ajax요청이기 때문에 위에 ResponseBody를 붙어야함
//전달하려는 값이 객체이므로 produces
return new Gson().toJson(list);
}
쪽지를 보낼 Controller
@ResponseBody
@RequestMapping(value="/insertDm.do")
public String insertDm(DM dm) {
int result = service.insertDm(dm);
return String.valueOf(result);
}
Service - insert이기 때문에 트랙잭션 관리를 해줌
@Transactional
public int insertDm(DM dm) {
return dao.insertDm(dm);
}
Dao
public int insertDm(DM dm) {
int result = sqlSession.insert("dm.insetDm", dm);
return result;
}
dmSQL
<insert id="insetDm" parameterType="dm">
insert into direct_message values(dm_seq.nextval, #{sender}, #{receiver}, #{dmContent}, sysdate, 0)
</insert>
받은쪽지List를 조회해올 Controller
@ResponseBody
@RequestMapping(value="/myDmList.do", produces = "application/json;charset=utf-8")
public String myDmList(DM dm) {
ArrayList<DM> list = service.selectDmList(dm);
return new Gson().toJson(list);
}
Service
public ArrayList<DM> selectDmList(DM dm) {
return dao.selectDmList(dm);
}
Dao
public ArrayList<DM> selectDmList(DM dm) {
List list = sqlSession.selectList("dm.selectDmList", dm);
return (ArrayList<DM>)list;
}
dmSQL
<select id="selectDmList" parameterType="dm" resultType="dm">
select
dm_no as dmNo,
sender,
receiver,
dm_content as dmContent,
to_char(dm_date, 'yyyy-mm-dd hh:mi:ss') as dmDate,
read_check as readCheck
from direct_message
<choose>
<when test="sender != null">
where sender = #{sender}
</when>
<when test="receiver != null">
where receiver = #{receiver}
</when>
</choose>
order by dm_no desc
</select>
'국비수업 > Spring' 카테고리의 다른 글
80일차 : AOP, Transaction, Schedul (0) | 2023.03.22 |
---|---|
79일차 : Dynamic Mybatis (0) | 2023.03.21 |
78일차 : Mybatis (0) | 2023.03.21 |
77일차 : SpringMVC - 게시판2 (0) | 2023.03.17 |
76일차 : 정규화, SpringMVC - 게시판 (0) | 2023.03.16 |