728x90
🔔 TODO : Ajax를 사용한 , 댓글 등록 , 댓글 수정, 삭제
📘 project : 인텔리제이 - SpringBootMybatisMini
form : content.jsp
dto : MbAnswerDto
controller : MbanswerController.java
Mapper : mbanswersql.xml
service : MbanswerMapperInter.java
스프링부트 동작관정 간단
- 클라이언트가 JSP 페이지에 데이터를 입력하고 제출합니다.
- JSP 페이지에서 컨트롤러에게 요청을 보냅니다.
- 컨트롤러는 요청을 받고 필요한 작업을 수행합니다.
- 컨트롤러는 서비스로 데이터 처리를 위임합니다.
- 서비스는 필요한 비즈니스 로직을 실행하고 데이터베이스에서 데이터를 가져옵니다.
- 서비스가 데이터 처리를 완료하면, 결과를 컨트롤러로 반환합니다.
- 컨트롤러는 JSP 페이지로 데이터를 전달합니다.
- JSP 페이지는 데이터를 이용하여 동적 웹 페이지를 생성하고 클라이언트에게 반환합니다.
결론 : 데이터 처리 후 반환되는 곳은 컨트롤러이다.
스프링부트가 동작하는 과정 대로 설명을 해보겠습니다.
form
<div style="margin : 50px 150px;">
<table class="table table-bordered" style="width:800px;">
<tr>
<td>
<h4><b>${dto.subject}</b>
<span style="font-size:0.7em; color:gray; float: right">
🔔 조회수 : ${dto.readcount}
🕰 작성일 : <fmt:formatDate value="${dto.writeday}" pattern="yyyy-MM-dd HH:mm:ss"/>
</span>
</h4>
<span><b id="myid" myid="${sessionScope.myid}">작성자 : ${dto.name} (${dto.myid})</b></span>
<c:if test="${dto.uploadfile!= 'no'}">
<span style="float:right">
<a href="download?clip=${dto.uploadfile}">
<i class="bi bi-arrow-down-circle"> </i><b>${dto.uploadfile}</b>
</a>
</span>
</c:if>
</td>
</tr>
<tr>
<td>
<c:if test="${bupload ==true}">
<img src="../savefile/${dto.uploadfile}" style="width:350px; height:400px;">
</c:if>
<br><br>
<pre>
${dto.content}
</pre>
<br>
<b>조회 수 : ${dto.readcount}</b>
<b>댓글 수 : <span class="acount"></span></b>
</td>
</tr>
<%--댓글--%>
<tr>
<td>
<input type="hidden" id="num" value="${dto.num}">
<div class="alist"></div>
<c:if test="${sessionScope.loginok != null}">
<div class="aform">
<div>
<input type="text" class="form-control" style="width:500px; display: inline-flex" placeholder="댓글 입력" id="content" >
<button type="button" class="btn btn-outline-danger" id="btnansweradd" num="${dto.num}">등록</button>
</div>
</div>
</c:if>
</td>
</tr>
<c:if test="${sessionScope.loginok!=null}">
<tr>
<td>
<button type="button" class="btn btn-outline-dark" onclick="location.href='form?currnePage=${currentPage}'" style="width:100px;">글작성</button>
<button type="button" class="btn btn-outline-dark" onclick="location.href='list?currnePage=${currentPage}'" style="width:100px;">목록</button>
<c:if test="${sessionScope.loginok!=null and sessionScope.myid ==dto.myid}">
<button type="button" class="btn btn-outline-dark" onclick="location.href='update?num=${dto.num}¤tPage=${currentPage}'" style="width:100px;">수정</button>
<button type="button" class="btn btn-outline-dark" onclick="location.href='delete?num=${dto.num}¤tPage=${currentPage}'" style="width:100px;">삭제</button>
</c:if>
</td>
</tr>
</c:if>
</table>
</div>
</body>
- 이 form에서는 client가 요청한 데이터를 list로 띄운 것이고, 그 list에서 댓글을 달기 위한 form입니다.
- form안에 <div.alist> 여기 div에 댓글을 띄울 예정입니다. 이 div에 댓글을 띄우기 위해서 ajax비동기방식으로 처리를 합니다.
다음으로는 Ajax를 처리하려면 Controller , service ,mapper에서 미리 메소드를 만들고 sql작성을 끝내놔야지 바로바로 ajax처리를 할 수 있으니 미리 만들어 보겠습니다
#1) dto
import java.sql.Timestamp;
import org.apache.ibatis.type.Alias;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@Data
@Alias("mbdto")
public class MbAnswerDto {
private String idx;
private String num;
private String name;
private String myid;
private String content;
@JsonFormat(pattern = "yyyyMMdd")
private Timestamp writeday;
}
- DB에 생성해둔 column 들이랑 이름을 같게 생성을 해줘야 합니다 (datatype은 달라도 상관없습니다)
- 여기서 중요한건 idx는 -> primary key이고
- num은 Mbanswer말고 그전에 생성한 memboard num이랑 foreign key를 주어 참조를 시킨 것 입니다.
- num은 댓글을 달기 전, 작성 된 글을 번호를 의미하는 것입니다
- 즉 작성된 글은 num으로 구별이고, idx는 그 작성된 글num 에 댓글을 다는 것이기 때문에 차별화를 둬야함.
#2) service 생성
-중요한건 service를 직접적으로 생성하지는 않았지만, 서비스 역할을 할 수 있는 클래스 입니다
- 왜 일까?? 라고 생각해봤는데 그것에 대한 답변은 다시 공부하고 업로드 하겠습니다.
package boot.data.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import boot.data.dto.MbAnswerDto;
@Mapper
public interface MbanswerMapperInter {
public void insertMbanswer(MbAnswerDto dto);
public List<MbAnswerDto> getAllAnswers(String num); //num 값에 따른 정보 넘기기
public MbAnswerDto getAnswer(String idx); //idx값에 따른 answer 값들 가져오기
public void updateMbanswer(MbAnswerDto dto);
public void deleteMbanswer(String idx);
}
- @Mapper 어노테이션은 -> Marker이다. 즉 이게 mapper를 처리하는 곳이다 라는걸 알려주는 어노테이션
- @Mapper을 상위 어노테이션은 @Repository 이다 -> @Repository는 bean에 등록을 시켜준다.
#3) mapper
<?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="boot.data.mapper.MbanswerMapperInter">
<insert id="insertMbanswer" parameterType="mbdto">
insert into mbanswer(num,name,myid,content,writeday) values (#{num},#{name},#{myid},#{content},now())
</insert>
<select id="getAllAnswers" resultType="mbdto" parameterType="String">
select * from mbanswer where num=#{num} order by idx desc;
</select>
<select id="getAnswer" resultType="mbdto" parameterType="String">
select * from mbanswer where idx=#{idx}
</select>
<update id="updateMbanswer" parameterType="mbdto">
update mbanswer set content=#{content} where idx=#{idx}
</update>
<delete id="deleteMbanswer" parameterType="String">
delete from mbanswer where idx=#{idx}
</delete>
</mapper>
- mapper에 들어가는 id들은 service에서 생성한 메소드 이름이랑 꼭 같게 해주어야 한다. 4
#4) controller
package boot.data.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import boot.data.dto.MbAnswerDto;
import boot.data.mapper.MbanswerMapperInter;
import boot.data.service.MemberService;
@RestController
@RequestMapping("/mbanswer")
public class MbanswerController {
@Autowired
MbanswerMapperInter mapper;
@Autowired
MemberService memberService;
@PostMapping("/ainsert")
public void insert(@ModelAttribute MbAnswerDto dto, HttpSession httpSession) {
//세션에서 저장한 아이디를 dto에 저장시킨다.
String myid = (String)httpSession.getAttribute("myid");
dto.setMyid(myid);
//세션에서 저장된 이름을 dto에 저장시킨다.
String name =memberService.getName(myid);
dto.setName(name);
mapper.insertMbanswer(dto);
}
@GetMapping("/alist")
public List<MbAnswerDto> alist(@RequestParam String num)
{
return mapper.getAllAnswers(num);
}
@GetMapping("/mbdelete")
public void adelete(@RequestParam String idx) {
mapper.deleteMbanswer(idx);
}
}
- Ajax로 데이터를 처리할 떄는 @Responsebody || @RestController 를 꼭 선언하고 해주어야 한다 아니면 컴파일에러
- insert할때는 @Modelattribute를 통해 MbanswerDto 값을 다 보내준다.
- 그리고 httpsession을 사용해서 , 세션에서 저장한 아이디를 보내줄 dto에 담아서 보내준다.
- 다른방식으로 미리 만들어둔 메서드를 통해서 name값을 같이 dto에 담아서 보내준다.
- List로 출력할 때는 간단하게, 반환하는 값은 당연히 dto값들이고, 이 dto값들을 list에 담아서 반환해준다
- 그리고 num값에 맞는 list를 출력해야 하기 때문에 num값 또한 매개변수 값으로 같이 보내주고 service에서 미리 작성해둔 메소드에 num을 담아서 return 해준다
- delete는 간단하게 댓글에 primary key인 idx에 따라서 삭제해준다.
#5) 마지막으로 form에서 위 모든 데이터들을 가지고 ajax 처리하는 코드를 보여드리겠습니다.
<script>
$(function(){
list();
$("#btnansweradd").click(function (){
var num = $(this).attr("num")
var content = $("#content").val();
var myid = $("#myid").attr("myid");
loginok = "${sessionScope.loginok}";
//alert(num+"_"+content+"_"+myid+"_"+loginok);
if(content.length==0) {
alert("댓글을 입력해주세요");
return;
}
$.ajax({
type:"post",
url:"/mbanswer/ainsert",
dataType:"html",
data : {"num":num,"content":content},
success:function (data){
alert("등록되었습니다.")
//댓글 수정창 띄우기
list();
//입력값 초기화
$("#content").val("");
}
})
})
//댓글 삭제
$(document).on("click","#del",function(){
var idx= $(this).attr("idx");
var a = confirm("삭제하시겠습니까?");
//alert(idx);
if(a) {
$.ajax({
type:"get",
dataType :"json",
url : "/mbanswer/mbdelete",
data : {"idx":idx},
success:function(){
location.reload();
}
})
}
})
// $("i.update").click(function(){
//
// })
})
function list() {
var num = $("#num").val();
//alert(num);
var loginok = "${sessionScope.loginok}";
var myid = "${sessionScope.myid}";
//alert(loginok + myid);
$.ajax({
type:"get",
dataType :"json",
url : "/mbanswer/alist",
data : {"num":num},
success:function(res){
$("span.acount").text(res.length);
var s = "";
$.each(res, function (i, dto) {
s += "<br>";
s += "<table class='table table-striped' style='width:800px; height:100px;'>"
s += "<input type='hidden' id='idx' value='idx'>";
s += "<tr>";
s += "<td><b> 🖐 작성자 : " + dto.name + "</b>" + "<span class='day' style='float:right'> 작성날짜 : "+dto.writeday+" ";
if(loginok!=null || myid ==dto.myid) {
s += "<i class='bi bi-trash3-fill' id='del' idx='"+dto.idx+"' style='cursor: pointer'></i> <i class='bi bi-clipboard-check update' style='cursor: pointer'></i></span></td>";
}
s += "</tr>";
s += "<tr>";
s += "<td> 📋 댓글 : " +dto.content + "</td>";
s += "</tr>"
s += "</table>"
});
$("div.alist").html(s);
}
})
//댓글 수정창 띄우기
}
</script>
- 댓글 등록 버튼을 누르면, 이벤트가 발생하고 댓글을 클릭해서 서버로 전송될 때는 list로 출력 될 값을 미리 설정해두고 ajax 처리를 해줘야합니다. ex) var content = $("#content").val();
- 댓글 창이 null값 즉 댓글창에 아무것도 없이 서버로 전송하려하면 댓글 입력하라는 알림이 뜬다
- 그리고 위 과정이 잘 되었다면 ajax를 통해서 데이터를 처리해준다.
다음으로는 ajax처리된 데이터들을 list로 띄웁니다.
- 이것 또한 ajax로 처리 했기 때문에 기존에는 댓글들이 다 보이고, 내가 댓글을 등록하면은 바로 맨위에 올라오게한다.
- $("span.acount").text(res.length); 이 코드는 댓글의 수를 출력하기 위한 코드이다.
다음은 삭제 입니다.
- 삭제하는 버튼에 미리 idx값을 심어놓습니다. 그리고 그 버튼이 클릭되면은 idx값을 가져오는게 중요합니다
- var idx= $(this).attr("idx");
- 그리고 무난하게 ajax처리를해서 삭제 하면 끝입니다
다음은 수정 입니다.
728x90